Math

The Balancer whitepaper describes a set of formulas derived from the value function for interacting with the protocol. The formulas in the Theory section are sufficient to describe the functional specification, but they are not straightforward to implement for the EVM, in part due to a lack of mature fixed-point math libraries.

Our implementation uses a combination of a few algebraic transformations, approximation functions, and numerical hacks to compute these formulas with bounded maximum error and reasonable gas cost.

Exponentiation Approximation

Approxing

Spot Price

SPio=BiWiBoWoSP^o_i = \frac{ \frac{B_i}{W_i} }{ \frac{B_o}{W_o} }

Where:

  • Bi is the balance of token i, the token being sold by the trader which is going into the pool.

  • Bo is the balance of token o, the token being bought by the trader which is going out of the pool.

  • Wi is the weight of token i

  • Wo is the weight of token o

When we consider swap fees, we do exactly the same calculations as without fees but using Ai(1swapFee)A_i \cdot (1-swapFee) instead of AiA_i. This strategy is referred to as charging fees "on the way in". With the swap fee, the spot price increases. It becomes then:

SPio=BiWiBoWo1(1swapFee)SP^o_i = \frac{ \frac{B_i}{W_i} }{ \frac{B_o}{W_o} } \cdot \frac{1}{(1-swapFee)}

Out-Given-In

In the whitepaper we derive the following formula that calculates the amount of tokens out –AoA_o– a trader gets in return for a given amount of tokens in –AiA_i, considering a Balancer pool without any swap fees:

Ao=Bo(1(BiBi+Ai)WiWo)A_{o} = B_{o} \cdot \left(1 - \left(\frac{B_{i}}{B_{i}+A_{i}}\right)^{\frac{W_{i}}{W_{o}}}\right)

To take into account the swap fees charged by the Balancer pool, we replaceAiA_iwithAi(1swapFee)A_i \cdot (1-swapFee). This is know as charging the fees "on the way in":

Ao=Bo(1(BiBi+Ai(1swapFee))WiWo)A_{o} = B_{o} \cdot \left(1 - \left(\frac{B_{i}}{B_{i}+A_{i} \cdot (1-swapFee)}\right)^{\frac{W_{i}}{W_{o}}}\right)

In-Given-Out

In the whitepaper we derive the following formula that calculates the amount of tokens in –AiA_i– a trader needs to swap to get a desired amountAoA_oof tokens out in return, considering a Balancer pool without any swap fees:

Ai=Bi((BoBoAo)WoWi1)A_{i} = B_{i} \cdot \left(\left(\frac{B_{o}}{B_{o}-A_{o}}\right)^{\frac{W_{o}}{W_{i}}}-1\right)

Since AiA_i is the amount the user has to swap to get a desired amount out AoA_o, all we have to do to include swap fees is divide the formula above by (1swapFee)(1-swapFee). This is because we know the fee charged on the way in will multiply that amountAiA_i by (1swapFee)(1-swapFee). This will cross out both terms (1swapFee)(1-swapFee) and the amount out will be AoA_o as desired:

Ai=Bi((BoBoAo)WoWi1)1(1swapFee)A_{i} = B_{i} \cdot \left(\left(\frac{B_{o}}{B_{o}-A_{o}}\right)^{\frac{W_{o}}{W_{i}}}-1\right) \cdot \frac{1}{(1-swapFee)}

All-Asset Deposit/Withdrawal

Anyone can be issued Balancer pool tokens (provided the pool is finalized) by depositing proportional amounts of each of the assets contained in the pool. So, for each token k in the pool, the amounts of token kDkD_k– that need to be deposited for someone to get PissuedP_{issued}pool tokens are:

Dk=(Psupply+PissuedPsupply1)BkD_k = \left(\frac{P_{supply}+P_{issued}}{P_{supply}}-1\right) \cdot B_k

Conversely, if a user wants to redeem their pool tokens to get their proportional share of each of the underlying tokens in the pool, the amounts of token k –AkA_k– a user gets for redeeming PredeemedP_{redeemed}pool tokens will be:

Ak=(1PsupplyPredeemedPsupply)BkA_k = \left(1-\frac{P_{supply}-P_{redeemed}}{P_{supply}}\right) \cdot B_k

All Balancer Protocol smart contracts were coded supporting a protocol-level exit fee to be charged that goes to Balancer Labs for supporting the development of the protocol. However, after careful consideration the Balancer Labs team decided to launch the first version of Balancer without any protocol fees whatsoever.

Single-Asset Deposit / Withdrawal

Single-Asset Deposit

In the whitepaper we derive the following formula that calculates the amount of pool tokens –PissuedP_{issued}– a liquidity provider gets in return for depositing an amount AtA_tof a single token t present in the pool:

Pissued=Psupply((1+AtBt)Wt1)P_{issued} = P_{supply} \cdot \left(\left(1+\frac{A_t}{B_t}\right)^{W_t} -1\right)

Since Balancer allows for depositing and withdrawing liquidity to Balancer pools using only one of the tokens present in the pool, this could be used to do the equivalent of a swap: provide liquidity depositing token A and immediately withdraw that liquidity in token B. Therefore a swap fee has to be charged for the amount of tokens that are deposited that would have to be swapped for an all-asset deposit.

Another way of justifying the need for charging a swap fee when a liquidity provider does a single-asset deposit is that they are getting a share of a pool that contains a basket of different assets. So in essence what they are doing is a trade of one of the pool assets (the token t being deposited) for all of the pool assets proportionally to their weights.

Since the pool already has a share of its value in token t, represented by the weightWtW_t, it only makes sense to charge a swap fee for the remaining proportion of the deposit At(1Wt)A_t \cdot(1 - W_t)

The formula then becomes:

Pissued=Psupply((1+(AtAt(1Wt)swapFee)Bt)Wt1)P_{issued} = P_{supply} \cdot \left(\left(1+\frac{\left(A_t-A_t\cdot(1 - W_t)\cdot swapFee\right)}{B_t}\right)^{W_t} -1\right)

The formula above calculates the amount of pool tokens one receives in return for a deposit of a given amount of a single asset. We also allow for users to define a given amount of pool tokens they desire to get – PissuedP_{issued}– and calculate what amount of tokens t is needed – AtA_t:

At=Bt((1+PissuedPsupply)1Wt1)A_t = B_t \cdot \left(\left(1+\frac{P_{issued}}{P_{supply}}\right)^{\frac{1}{W_t}} -1\right)

Taking into account the swap fees we have:

At=Bt((1+PissuedPsupply)1Wt1)(1Wt)swapFeeA_t = B_t \cdot \frac{\left(\left(1+\frac{P_{issued}}{P_{supply}}\right)^{\frac{1}{W_t}} -1\right)}{(1 - W_t)\cdot swapFee}

Single-Asset Withdrawal

The withdrawal formulas are the inverse of the deposit formulas if no swap fees are considered. In other words, if you deposit a given amount of token t for pool tokens and then immediately redeem these pool tokens for token t again you should receive exactly what you started off with.

The formula without considering swap fees is then:

At=Bt(1(1PredeemedPsupply)1Wt)A_t = B_t \cdot \left(1-\left(1-\frac{P_{redeemed}}{P_{supply}}\right)^\frac{1}{W_t}\right)

Where AtA_t is the amount of token t one receives when redeeming PredeemedP_{redeemed}pool tokens.

Considering swap fees we have the following:

At=Bt(1(1PredeemedPsupply)1Wt)(1(1Wt)swapFee)A_t = B_t \cdot \left(1-\left(1-\frac{P_{redeemed}}{P_{supply}}\right)^\frac{1}{W_t}\right)\cdot \left(1-(1 - W_t)\cdot swapFee\right)

If there were an exit fee it would be taken from the amount of tokens redeemed PredeemedP_{redeemed}but as mentioned above this fee has been chosen to be zero in the first version of Balancer.

Balancer also allows for a liquidity provider to choose a desired amount of token t, AtA_t, they would like to withdraw from the pool and calculates the necessary amount of pool tokens for that,PredeemedP_{redeemed}. The formula without considering swap fees is:

Predeemed=Psupply(1(1AtBt)Wt)P_{redeemed} = P_{supply} \cdot \left(1-\left(1-\frac{A_t}{B_t}\right)^{W_t} \right)

Where AtA_t is the amount of token t one receives when redeeming PredeemedP_{redeemed}pool tokens.

Considering swap fees we have the following:

Predeemed=Psupply(1(1At(1(1Wt)swapFee)Bt)Wt)P_{redeemed} = P_{supply} \cdot \left(1-\left(1-\frac{\frac{A_t}{\left(1-(1 - W_t)\cdot swapFee\right)}}{B_t}\right)^{W_t} \right)