Interest-Bearing Stablecoin Pools Without Impermanent Loss

Fernando Martinelli
Balancer Protocol
Published in
10 min readOct 30, 2019

TLDR: You can earn higher yield by putting your stablecoins in this Balancer pool than you would by simply lending them on Compound. It’s like cDAI but with the upside of also getting trading fees accrued over time in the pool.

On a more technical level, this Balancer stablecoin pool design uses rTokens and automatic weight adjustment to benefit from both trading fees and lending interests while avoiding impermanent loss.

Since the publication of our whitepaper a few weeks ago we have been contacted by a lot of people in the Ethereum community (other projects, investors and users). Some of our ideas have been resonating very positively, and we will do our best to share them in a more structured way.

The “stablecoins only” Balancer pool seems to be a favorite. We see three main reasons for that:

  • Current lack of liquidity among stablecoins: With the exception of USDT, liquidity of Ethereum stablecoins is not the best. If we focus specifically on non-custodial liquidity, the situation is even worse. Those trading from one stablecoin to another usually incur painful costs — in both fees and slippage.
  • No expected impermanent loss¹: To recap, impermanent loss is defined as the difference between the value of a zero-fee Balancer pool and the value of just holding those same tokens. The more the prices of tokens inside a pool diverge in any direction, the greater the impermanent loss. Since the relative prices between all stablecoins in the pool are expected to remain constant (as long as none of them fail), liquidity providers bear less risk and could feel more confident about trading fee revenues actually turning them a profit.
  • Room for very low trading fees: This is tightly connected to the point above. Since virtually all trading fees collected are expected to become profit, liquidity providers of stablecoin pools are exposed to less risk than those of other typical Balancer pools. They can therefore afford to charge low trading fees — remember that Balancer protocol allows for the choice of any trading fee. These appealing trading conditions could attract to Balancer significant volume from other venues — be they DEXs or CEXs.

The simple approach

One could create for instance a Balancer pool that contains 55% DAI, 30% USDC and 15% PAX.

However, potential liquidity providers would inevitably compare the potential returns of this pool against other more profitable options for deploying capital in DeFi, such as today’s popular lending platforms.

A more sophisticated approach

Instead of creating a pool with DAI, USDC and PAX, an idea would be to first lend DAI and USDC on a lending platform, like Compound, and then create a pool with their respective lending vouchers (cDAI, cUSDC) and PAX (which to date is not yet available for lending on Compound).

However, since the interest rates offered on Compound for each of these assets is usually different, the price ratio between them would naturally change over time. This could cause impermanent loss for liquidity providers of the pool. Even worse, such loss might not be impermanent since systemic interest rate discrepancies are expected among different stablecoins. In other words, over the long run the price ratio between those cTokens is expected to diverge.

The UX for traders also degrades since the real price of the underlying tokens originally lent becomes a bit obscured: “How much in actual DAI is cDAI worth now? Is the current cDAI/cUSDC price ratio in a Balancer pool reasonable (i.e. in accordance with the external market)?’’. Unfortunately, less straightforward pricing negatively impacts trading volume, which of course is bad news for liquidity providers.

The best of both worlds

It is possible for liquidity providers to earn trading fees from a stablecoin Balancer pool WHILE ALSO accruing interests from lending platforms with no expected impermanent loss.

To make this possible while keeping a great trader UX we need to introduce a wrapper of the stablecoins used that maintains their pegged value while also benefiting from the interests generated on lending platforms. One such solution that has gained prominence lately is the rDAI project.

rDAI makes it possible for users to hold an asset that maintains the USD peg (i.e. redeemable 1 to 1 for DAI) while still earning interests from Compound or other lending platforms. Credit to the rDAI team.

Instead of a Balancer pool with cTokens, one could create a pool comprised of rTokens. The payout of interests created by the rTokens can be triggered by anyone. Without having set up a specific beneficiary for the interests, these go by default to the holder of the rTokens, in this case the Balancer pool.

Although straightforward, this simple design would generate arbitrage opportunities whenever anyone called function payoutInterests() for any of the rTokens in the pool. To understand why, remember that the prices in a Balancer pool are defined by the token weights and balances. The execution of payoutInterests() would increase the balance of a single token, making it instantly cheaper against any other token in the pool. The profits of the arbitrageurs would come at the expense of the liquidity providers of the pool.

Balancer pools controlled by smart contracts

Balancer protocol has been designed from the ground up to be a building block for other projects and developers in the ecosystem. As such, flexibility is one of the core features of Balancer, and it comes in two flavors:

  • Tokens inside pools: Any ERC-20 fully compatible token can be held by Balancer pools. Synthetics, derivatives, wrappers, vouchers… they are all welcome.
  • Control of Balancer pools: Controlled/private pools² only accept liquidity from their controller. Since third parties are forbidden from providing liquidity, with this type of Balancer pool the controller may safely change token weights, add/remove tokens and even change the trading fee. The key point here though is that pool controllers can be smart contracts, embedding any desired logic on how to manage their controlled pools.

The stablecoin pool controller

A smart contract (let’s call it contract PC) that controls a controlled Balancer pool (let’s call it contract BP) can easily emulate shared/finalized pools. Finalized pools accept liquidity from any third party but their creators have no special rights and their parameters can never be changed.

PC can accept liquidity, forward it to BP and mint its own ERC-20 tokens that represent ownership of BP.

(1) anyone providing liquidity in rTokens to the pool does so by depositing to PC, the controller of BP; (2) before transferring rTokens to BP, PC sets itself as the beneficiary of the interests; (3) PC issues its own ERC-20 tokens representing ownership in BP;

This is especially useful for our stablecoin pool example. If the interests paid by the lending platform were forwarded directly into the Balancer pool, we would generate arbitrage opportunities as described above. To solve this problem, the owner contract PC could set itself as the beneficiary of the rTokens before forwarding them to BP. As such, when PC received the interests in rTokens on behalf of BP, it would make sure to receive the outstanding interests of all tokens before forwarding them to BP. This would end up increasing all token balances, decreasing a lot the arbitrage opportunities that would cause losses for liquidity providers.

(1) anyone can call function processInterests() on BP; (2) PC then calls payoutInterests(“BP”) for all rTokens to make sure there are no outstanding interests remaining. (3) Interests in rTokens are paid out to PC, which is the beneficiary of BP; (4) rTokens are then all sent by PC to BP to increase its liquidity.

Since the total supply of PC-tokens (which represent indirectly ownership of all the liquidity inside BP controlled by PC) does not change when interests are paid out and forwarded to the pool, the owners of PC-tokens benefit directly from the lending interests. They also benefit from the trading fees being paid by traders using the stablecoin pool to trade across different stablecoins, just like in any other Balancer pool.

From little to zero impermanent loss

We know that different stablecoins have different lending rates on platforms like Compound. This would result in some small impermanent loss over time. To help us understand why, let’s consider a very simple example. Let’s say that we start a Balancer stablecoin pool with 50% rDAI and 50% rUSDC. Say the initial balances of both rTokens are 100, which means that their relative price is 1:1 (please refer to the Balancer whitepaper to understand how spot prices are calculated in Balancer pools). Imagine that, after a couple of months, the 100 rDAI generated interests of 2 rDAI while the 100 rUSDC generated only interests of 1 rUSDC.

When anyone pokes the rToken contracts, these interests are sent to the beneficiary: the pool owner PC as explained above. Contract PC has a function that can also be triggered by anyone that forwards the outstanding interests of all tokens at once to the pool (i.e. it makes sure to call function payoutInterests() for all rTokens). In the example above, consider for simplicity’s sake that the relative price between DAI and USDC has stayed constant at 1:1 and no fees have been collected. The balances of the pool would go from 100 rDAI + 100 rUSDC to 102 rDAI + 101 rUSDC after the interests are paid out.

Again, according to Balancer’s price calculations, this would result in a change in relative price from 1:1 to 102:101 (or 1.01:1 approximately). rDAI would become slightly more abundant than rUSDC in the pool, thus slightly cheaper in rUSDC terms. Considering a rational market, this would open up an arbitrage opportunity for traders, which would be equivalent to having impermanent loss. That is, arbitrageurs would profit from the imbalance created by the different interest rates paid to the pool at the expense of liquidity providers.

The solution: updating weights

The flexibility offered by controlled Balancer pools can be used in our favor in this case. While receiving interests and forwarding them to BP, PC can also adapt the weights of BP tokens to compensate for the imbalance created by their different lending rates. All atomically so that arbitrageurs never get the chance to profit off of pool liquidity providers.

To illustrate this, let’s consider the previous example again. When contract PC pulls the 2 rDAI + 1 rUSDC interest, it forwards them to the pool. In this same transaction the weights can be updated from 50% : 50% to 50.2463% : 49.7537% (or 102/203 : 101/203). This way the new balances and weights in the pool will result in exactly the same 1:1 price from before the interest payout, which effectively avoids impermanent loss.

Any function that updates the PC-token supply (joining or exiting the pool) should include the housekeeping task of redeeming rToken interests, along with the subsequent tasks needed for the pool to be fully updated (forward interests to BP + update weights) before any minting/burning of PC-tokens.

One could argue that this continuous weight updating would, over time, cause the pool to be comprised of predominantly the coin that has the higher interest rate. While this is true, that effect happens very slowly. For example, consider a pool starting with 50/50 weights for rDAI and rUSDC and lending rates of respectively 5% and 3% per year. It would take 22 years for the pool to reach 60/40 weights and 45 years for it to reach 70/30 weights.

Of course, by affirming this pool will have zero expected impermanent loss we are assuming the change in the relative price of the tokens within the pool in the long term should be negligible, that is, we assume none of the stablecoins in the pool fails.

Smoothing the UX

As a nice-to-have, the pool controller could deal not only with rTokens but also with cTokens and the underlying stablecoins, allowing the trader to use (send/receive) whatever versions they please by abstracting away all necessary (un)wrappings.

If for instance they own cDAI and would like to exchange it for USDC, PC should accept the input as is and deliver the desired output token, even if the trade itself at BP is from rDAI to rUSDC.

Upgrading the pool

There are many situations in which it would be desirable to allow liquidity providers to consensually update the terms of the proposed stablecoin pool after it’s already live. They might want to:

  • change the trading fee
  • reset weights to their original values
  • include a new popular stablecoin
  • switch from PAX to rPAX, when PAX becomes available on Compound
  • switch lending platforms
  • switch wrappers (the rTokens)
  • migrate to Balancer v2 after it launches

Today our ecosystem still lacks mature tools to govern a DAO securely and with simplicity. So at least for a first version of the proposed stablecoin pool, it seems wiser not to implement a governance mechanism for the PC contract. This way, whenever some liquidity providers feel that their needs are better covered by a pool with different parameters and they expect that enough liquidity would gather at the new pool, they may go ahead and deploy such a pool separately and migrate their liquidity from the previous pool.

Conclusion

We proposed a new controlled Balancer pool architecture that uses a smart contract as pool owner allowing for stablecoin liquidity providers to earn not only Balancer trading fees but at the same time also impermanent-loss-free lending interests. This is only possible thanks to the highly flexible characteristics of Balancer controlled pools, such as dynamically updating token weights.

The fact that the pool is comprised of rTokens is also a great UX improvement over holding for instance directly cTokens (the actual vouchers for lent liquidity on Compound). While rTokens keep a 1:1 peg to the underlying tokens, cTokens continuously accrue value, confusing traders as to what their current fair market price should be.

The purpose of this article was to illustrate yet another interesting use case our team sees for Balancer protocol. If you are interested in building the proposed architecture or even improving on it, please contact us to discuss further details. We are confident many more interesting applications will be developed by the community and we are very happy to assist as much as we can.

My special thanks to FollowTheChain, Alex Evans, Dan Robinson, Markus Koch and the whole rDAI team for their invaluable contribution to this article.

[1] For more details on what impermanent loss refer to this article by Pintail.

[2] Check out our whitepaper for more details on the differences between controlled and finalized pools.

--

--