In this post, we’ll explore the dynamic weighting and staking features of a new type of liquidity pool in Bancor v2 called a Dynamic Automated Market Maker (DAMM).
The process below allows for automated market-making on any staked asset supported by a reliable price oracle, and is designed to maintain the value of liquidity provider (LP) contributions over time using dynamic parameters in the pool.
In other words, all LPs in the pool should be able to withdraw the same amount as they staked plus a share of fees that the pool earned during their staking period.
Core concepts of v2 pools are:
- Single-Reserve Pool Tokens: Each v2 pool is anchored to two pool tokens (one per reserve).
- Staked Balance and Current Balance: For each reserve, staked balance indicates the total amount of tokens staked by liquidity providers, and current balance indicates the amount of tokens held in the reserve.
- Dynamic Weights: The pool updates reserve weights to incentivize market participants to equalize the current balance with the staked balance.
- Price Feeds: Price feeds are used for calculating the weights such that after arbitrage closure, the pool price becomes equal to the market price.
Single-Reserve Pool Tokens
In existing AMMs, users provide liquidity to a pool in exchange for pool tokens. These pool tokens track a liquidity provider’s share of the pool across multiple reserves.
In Bancor v2, we’ve made a key change: a v2 pool issues a separate pool token for each reserve. This simplifies the process of tracking liquidity provider contributions: Instead of one pool token tracking stakes across multiple reserves, each pool token now represents a stake in one reserve.
Note that while in existing AMMs there is only one pool token per pool, each v2 pool is anchored to exactly two pool tokens (one per reserve).
This creates two sets of liquidity providers for each pool:
- Primary Reserve LPs— provide liquidity in a primary reserve token (hereinafter referred to as “XYZ”) in exchange for XYZ Pool Tokens (ERC20)
- Secondary Reserve LPs — provide liquidity in a secondary reserve token (hereinafter referred to as “BNT”) in exchange for BNT Pool Tokens (ERC20)
Within each v2 pool, a conversion generates a fee in the reserve of the requested token. For example, an XYZ to BNT conversion generates a fee for the BNT reserve.
In addition, when liquidity providers add or remove liquidity, the pool’s weights automatically adjust to account for the change in reserve value — for example, increasing the weight of a reserve when it receives liquidity.
Staked Balance and Current Balance
Existing liquidity pools, including Bancor v1, expose liquidity providers to a downside risk called impermanent loss: Whenever the relative external market price of the asset diverges from the price at which liquidity was provided, the value that the provider can withdraw is smaller than the value he or she staked.
V2 pools are designed to mitigate this risk by incentivizing market participants to always equalize the total held in the reserves (“current balance”) with the amounts staked by liquidity providers (“staked balance”).
When a user stakes liquidity in a v2 pool, the amount of tokens deposited is recorded by the pool. The pool’s “staked balance” is a record of the pool’s obligation to its liquidity providers. The pool always aspires to have sufficient tokens to cover this obligation.
The important trade-off in v2 is that sometimes the current balance in the pool is insufficient for backing the pool’s total obligations to liquidity providers. Sounds worse than impermanent loss, right? Wrong.
When a pool’s current balance is not equal to its staked balance, the pool’s weights are adjusted in order to incentivize arbitrageurs to return the primary reserve token balance back to its staked balance. Subsequently, the secondary reserve token balance also gets closer to its staked balance. Although the arbitrage incentive does not push the secondary reserve token balance 100% back to equilibrium, frequent arbitrage operations guarantee that it always remains very close (slightly below or above) to its staked balance.
In the image below, you can see that roughly 50 percent of arb closures cause the pool to receive a surplus of BNT, while roughly 50 percent cause a BNT shortage. Assuming fast-reacting arbs, over time, the pool pushes the BNT current balance to closely track the staked balance.
Hence, in existing liquidity pools with volatile assets, a liquidity provider is pretty much guaranteed to get back less tokens than they staked. However, a liquidity provider in a Bancor v2 pool is pretty much guaranteed to get back the tokens they staked, under the condition that on rare occasions they may need to withdraw their stake gradually.
So how do v2 pools ensure liquidity providers can cash out their staked balance frequently enough? Dynamic weights play a key role in generating the right incentives for arbitrageurs to continuously refill reserves.
The arbitrage incentive is always to convert BNTs to XYZs or vice-versa, such that the following conditions are met:
- BNT/XYZ pool price= BNT/XYZ market price
- XYZ current balance = XYZ staked balance
To demonstrate this, let’s denote the current XYZ balance as “s” and the staked XYZ balance as “t”.
Consider the case of “s < t”. Our goal is to set the weights of the pool, such that the arbitrage incentive of equalizing the pool price and a reference market price will subsequently increase “s” to become equal to “t”. In other words, we want the arbitrager to transfer “t − s” XYZs to the pool, in exchange for BNTs.
This means that whenever there is a shortage in XYZs and the pool is unable to pay back its obligation to XYZ providers, the pool creates an incentive for the market to immediately fix the deficit.
The exact same mechanism is applied in the case of “s > t”, which illustrates a surplus in XYZs.
What about the BNT side? Unlike the XYZ side, which is guaranteed to remain in equilibrium (where XYZ current balance = XYZ staked balance), the BNT side is not. However, it is nevertheless pushed in the right direction whenever arbitrage is closed. The more frequently arbitrage is closed, the closer BNT stays to equilibrium.
In the event that market actors need some extra motivation to restore balance to the pool, v2 pools introduce a dynamic fee to nudge the market in the right direction.
Two types of price feeds provide continuous updates to v2 liquidity pools: external feeds and internal feeds. To demonstrate the functionality of both feeds, let’s walk through two example market scenarios.
Let’s take the case of a newly initialized pool where the two asset balances are equal. Here’s a snapshot of our example pool at this step:
1. XYZ Price Increases Significantly
In existing AMMs, when the price of one asset diverges from the other asset, LPs suffer impermanent loss because the ratio between these two assets remains fixed. Arbitrageurs are quick to pick up on these imbalances and they extract value from LPs by trading the overvalued asset for the undervalued one.
In the case of Bancor v2, oracles pick up on these changes in price and adjust the weights of each reserve accordingly. When the XYZ price increases, the target weight of XYZ in the XYZ/BNT pool will rise and there will be no opportunity for arbitrage.
Referring back to our initial pool, let’s consider the impact of a 10% increase in the price of XYZ.
When the external oracle updates, the target weight of XYZ automatically adjusts to 52%, consistent with the changes in the value of the asset reserves.
2. XYZ Price Increases Marginally
External oracles capture significant movements in the prices of reserve assets and protect LPs from impermanent loss. However, in order to most precisely price reserve assets, v2 pools also make sure to account for micro-changes in market sentiment. Each pool includes an internal price feed derived from the simple moving average (SMA) over the preceding ten minutes. On each update from the external oracle, the internal price feed re-anchors to the external oracle and the continuous SMA calculation restarts.
Consider the scenario below. After one minute and one conversion, the internal price feed and reserve target weights have adjusted slightly.
If, for example, no further trades are recorded in the following three minutes, the internal price feed will have three more minutes of data and that information will be reflected in the pool price (Step D).
While the core V2 smart contracts are finished, additional work is still in progress:
- Bancor V2 smart contracts are undergoing formal verification and security auditing by Consensys Due Diligence & 1inch.exchange.
- A live bug bounty encourages additional community security review.
- The Bancor.Network front-end is being updated to work with Bancor V2, including trading, pool staking and network analytics.
- Bancor V2 Documentation, guides, and examples are still being worked on.
Pending a successful formal verification, we are optimistic that Bancor V2 will be deployed in the coming weeks. However, please keep in mind that this is a target and not an announced release date.
We look forward to continued feedback and involvement from the fantastic Bancor community. To get involved and stay up to date:
- Join the community on Telegram: Bancor Protocol channel & Bancor Developer channel
- Follow Bancor on Twitter
- Subscribe to the Bancor blog
- Announcing REN and renBTC as Bancor V2 Launch Pools
- Guide: How to Provide Liquidity on Bancor
- Announcing Bancor V2
- Incentivizing Network Liquidity with Bancor Staking Rewards
- Designing Capital Efficient AMMs in Bancor V2
- What Sets Bancor Apart From Other DEXs