Proposal to add Balancer BPTs as collateral on IP
This proposal is to begin adding Balancer LP tokens as supported collateral by Interest Protocol. Balancer LP tokens are yield-bearing tokens that accrue yield to the owners from fees and rewards. This proposal is for Balancer LP tokens generally, and B-stETH-STABLE specifically as a first Balancer LP collateral.
Interest Protocol and GFX Labs have worked to implement measures to add Balancer LP tokens as collateral, and to stake these for Aura Liquidity Provider reward tokens while in the Interest Protocol vaults, giving borrowers the ability to stake these assets where applicable, as well as the ability to claim any rewards for staking.
This proposal will require an upgrade to the existing VotingVaultController, to allow it to track the new vault type as well as registered BPTs.
The first asset to be proposed for listing is B-stETH-STABLE. This is a MetaStablePool on the Balancer protocol. MetaStablePools are made up of two assets that are tied together in some way, where one is generally pegged to the other. In this case, the assets are wstETH and wETH. MetaStablePools like this one incorporate a rate provider contract to determine the exchange rate between the two assets.
Like most other assets on Interest Protocol, the collateral will be wrapped by a Cap contract in order to limit the total supply allowed on the protocol, thus mitigating liquidity risk. In this case it will be wrapped by a new CappedBptToken Contract.
While the goal is to end up with a staked Aura Reward Token in the Interest Protocol vault as collateral, these tokens are not able to be transferred, so users must deposit regular Balancer LPs (BPTs) such as B-stETH-STABLE, and these must then be staked on Aura in exchange for the reward token. This staking is, of course, done in an automated way upon deposit into a user’s vault.
The reasoning for this is because if we look at the holders of B-stETH-STABLE on Etherscan, we can see that the overwhelming majority of these BPTs are held by the Gauge Contract. This is because in order to maximize rewards for your BPT, it should be staked on the corresponding gauge contract, in exchange for these Gauge Tokens.
However, if we further look at the holders of the gauge token, we can again see that the overwhelming majority are held by the Aura Voter Proxy. This is because one can further increase rewards by staking through the Aura Finance infrastructure, which stakes deposited BPTs for Gauge Tokens, then consolidates the voting power into the single Aura Voter Proxy contract.
So we can see that the majority of stakers are providing liquidity through the Aura Finance infrastructure, as the holders of the Aura Reward Token have a good distribution. Unfortunately, the Aura contracts do not allow the deposit of Gauge tokens for staking, only the underlying BPT, so this is why on Interest Protocol the listed asset will be the BPT, rather than the Gauge Token or Aura Reward Token.
Because BPTs, Gauge Tokens, and Aura Reward Tokens are all issued 1:1 with each other, our oracle can price all of them at the same value.
Staking is done via the Aura Booster Contract, which handles all of the staking, and delivers the Aura Reward Token in exchange for the underlying BPT. The logic to handle this is on the new version 3 Vault on Interest Protocol, the VaultBPT.
Token Address: 0x32296969Ef14EB0c6d29669C550D4a0449130230
Capped Token address: Capped BPT contract
Liquidation incentive: 8%
Maximum Cap: 100k USD
Primary oracle: OutGivenIn oracle
Secondary oracle: MinSafePrice oracle
Price deviation: 5%
Market Cap: $110,000,000 USD
Liquidity: Redeemable at any time for underlying tokens of the pool
Volatility: Similar to ETH
24h volume: $4,250,000
90d volume: $427,250,000
Notable exchanges: Balancer Protocol
Type of contract: LP token
Underlying asset: wETH/wstETH
Time: 653 Days (Created August 17, 2021)
Privileges: Balancer Governance
Supplemental Information: Please read below for details on staking and how the primary risk (oracle manipulation) is addressed.
Staking In Detail
Staking BPTs while using them as collateral presents some challenges.
The first of which is that if the Aura Reward Token is not transferable, how do we liquidate a position if needed?
In order to achieve this, the transfer function of the VaultBPT is overridden to automatically unstake any staked BPTs therein. As the transfer function should only be called upon liquidation or withdrawal, this results in a smooth transition of staked illiquid Aura Reward Tokens to transferable BPTs.
In the case of a partial liquidation, all of the staked Aura Reward Tokens will be unstaked, but not all of the underlying BPTs will be transferred out from the Vault, so the vault owner will need to stake again in order to maximize the rewards.
Another challenge is that the staking of BPTs into Aura Reward Tokens happens differently than staking AuraBal, and we wanted the new vault type to be able to handle both.
AuraBal is similar to BPTs in the sense that it can be staked for Aura Reward Tokens, however rather than being an LP for the Balancer Protocol, AuraBal represents liquid veBal, (Vote Escrowed Balancer BPT). This token is not transferable, and represents the voting power for the Balancer protocol. More about veBal can be read about in the Balancer Docs, and more about AuraBal can be found in the Aura Docs.
Essentially, AuraBal can be staked by simply calling stakeAll() on its corresponding Aura Reward Token, whereas regular BPTs must first be staked into Gauge Tokens which must be sent to the Aura Voter Proxy contract in the correct way. Therefore, staking of normal BPTs happens via the Aura Booster Contract.
As part of the asset listing process, BPTs are associated with their corresponding Aura Reward Token so that staking can take place.
Claiming of Rewards
Rewards can be claimed regardless of liability, including support for extra rewards (supported by some Aura Reward Tokens).
Claiming of extra rewards is an optional bool argument when calling claimAuraLpRewards() on the VaultBPT contract. Claiming extra rewards is gas intensive and so should not be done if there are no extra rewards to be claimed.
Rewards are always sent to the vault minter, and as such claiming rewards is not a permissioned function.
Claiming of rewards has the possibility of doing a solvency check if needed. While this consumes a lot of extra gas, it is needed because if any of the rewards or extra rewards tokens happen to be a BPT registered as collateral, then claiming rewards would transfer out all of the collateral without regard for any liability that may exist on the vault.
The solvency check only happens if the rewards or extra rewards tokens happen to be a BPT registered as collateral, otherwise, the solvency check is skipped, saving about 450k gas.
Original Oracle System
By far the biggest hurdle to this project is coming up with a robust and accurate oracle system to price BPTs as collateral.
The naïve approach to pricing an LP token is to simply gather the total asset values that back the LP (total balance of each asset multiplied by a known price) and divide by the total supply of the LP. So LTV / Total Supply.
We can call this price the naïve price, and if manipulation were not a factor, this would be the ideal price to use when deriving a value for BPTs as collateral on Interest Protocol.
If priced this way, a flash loan attack could manipulate the underlying asset balances in a significant enough way to alter the price of the LP token for a single block, allowing for malicious actions such as inflating the ‘price’ of the BPT, so a borrower on IP can borrow more than they should against their BPT collateral. If this attack can alter the balances enough to inflate the BPT price to a greater extent than the LTV, an attacker could walk away with a profit in borrowed USDi, leaving some bad debt behind.
A solution to price BPTs from Weighted Pools was already developed in principle by Revest Finance as described in this article. The implementation for weighted pools works based on this formula and has been tested to be accurate.
Importantly, this solution does not even ask the Balancer Vault what the pool balances are, yet is still able to accurately calculate the LTV of the pool, and so should be safe and resistant to manipulation.
The solution to solving this problem for StablePools / MetaStablePools unfortunately is less straightforward.
StablePools differ from MetaStablePools in that they are made up of two assets that are often similar in value, rather than two otherwise related assets. For example, the stable pool B-auraBAL-STABLE is a pool between AuraBal and the BPT B-80BAL-20WETH, which is the unstaked version of veBal. Therefore, these two should be roughly equal in value, as they represent the same underlying asset and functionality.
The solution recommended by Chainlink via this article is to use a method that we can call MinSafePrice. This method is supposed to calculate a safe lower bound for the true price of the BPT. Protocols can then use this MinSafePrice as the market price for the BPTs, resulting in a safe (if slightly undervalued) price for the collateral.
However, in testing, the results of this method are often slightly higher than the expected naïve price, which doesn’t make much sense if this price is supposed to be a lower bound.
After trial and error with a number of other possible solutions, the best solution currently tested is to utilize the outGivenIn logic to determine if manipulation has taken place.
In essence, we can know the market exchange rate of the two assets in the pool if we can price them with external oracles. We can then compare this to the price rate computed by the pool.
This pool price rate is of course subject to manipulation, but we can detect this manipulation by comparing the result to the true market exchange rate.
In this way, we can confirm that manipulation has not taken place, and therefore utilize the naïve price.
More info on this can be found in this full technical writeup of the oracle systems.