Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
849 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# BIP-16: Whitelist BEAN:LUSD Curve Pool | ||
|
||
- [Proposer](#proposer) | ||
- [Summary](#summary) | ||
- [Proposal](#proposal) | ||
- [Economic Rationale](#economic-rationale) | ||
- [Technical Rationale](#technical-rationale) | ||
- [Effective](#effective) | ||
|
||
## Proposer: | ||
|
||
Beanstalk Farms | ||
|
||
## Summary: | ||
|
||
Add the BEAN:LUSD Curve pool to the Silo whitelist for 1 Stalk and 3 Seeds per flash-loan-resistant Bean denominated value (BDV) Deposited. | ||
|
||
## Proposal: | ||
|
||
Add LP tokens for the BEAN:LUSD Curve pool (X) to the Silo whitelist. | ||
|
||
**Token address:** 0xD652c40fBb3f06d6B58Cb9aa9CFF063eE63d465D | ||
|
||
**BDV function:** The BDV of BEAN:LUSD LP tokens is calculated from the virtual price of X, the LUSD price in 3CRV derived from the LUSD:3CRV pool (lusd3CrvPrice), and the BEAN price in 3CRV derived from the BEAN:3CRV pool (bean3CrvPrice). | ||
|
||
Both lusd3CrvPrice and bean3CrvPrice are calculated using the getY() function in the curve metapool contract using the reserves in the pools in the last block ($\Xi - 1$). | ||
|
||
We propose the BDV function for X is: | ||
$$ | ||
BDV(x) = x * \text{virtual_price}(X) * \text{min}(1, \text{lusd3CrvPrice} / \text{bean3CrvPrice}) | ||
$$ | ||
**Stalk per BDV:** 1 Stalk per BDV. | ||
|
||
**Seeds per BDV:** 3 Seeds per BDV. | ||
|
||
## Economic Rationale: | ||
|
||
Adding the BEAN:LUSD Curve pool to the Silo whitelist is beneficial to the success of both Beanstalk and Liquity. While the Silo’s yield should attract initial capital to the pool, the Stalk and Seed system incentivizes long-term liquidity that helps to further stabilize the prices of both BEAN and LUSD. | ||
|
||
Over $300M in LUSD is currently deposited in Liquity's Stability Pool, earning ~6.3% APR from LQTY early adopter rewards at this time. The emission of these LQTY rewards follows a yearly halving schedule, and the Liquity Stability Pool holds more LUSD than is necessary to cover liquidations. | ||
|
||
If BIP-16 is passed, the BEAN:LUSD pool’s inclusion in the Silo will offer LUSD holders the opportunity to directly participate in Beanstalk's governance and yield opportunities, providing additional utility to LUSD. | ||
|
||
The pool is likely to attract capital from both BEAN holders and LUSD holders. The Silo’s Stalk and Seed system will reward long-term liquidity and should increase the stickiness of the capital in the pool. The pool also helps to decrease BEAN price deviations from peg and diversifies BEAN liquidity, increasing its correlation with a stable asset and reducing the correlation of its price with a more volatile asset like Ether. | ||
|
||
The BEAN:LUSD Curve pool was launched on March 24, 2022, and currently holds over $500,000 in BEAN and LUSD. There is no capital requirement for a pool to be added to the Silo whitelist—the pool will be whitelisted upon the passage of this BIP. | ||
|
||
## Technical Rationale: | ||
|
||
By using the virtual price and the reserves in the last block, the BDV function is flash-loan-resistant. | ||
|
||
## Effective: | ||
|
||
Effective immediately upon commit. | ||
|
||
## Reward: | ||
|
||
5,000 Beans to Beanstalk Farms. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
pragma solidity ^0.7.6; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "../../C.sol"; | ||
import "../../libraries/Curve/LibBeanMetaCurve.sol"; | ||
import "../../libraries/Curve/LibBeanLUSDCurve.sol"; | ||
import "../../libraries/LibBeanEthUniswap.sol"; | ||
|
||
/* | ||
* @author Publius | ||
* @title BDVFacet holds the Curve MetaPool BDV function. | ||
*/ | ||
contract BDVFacet { | ||
|
||
using SafeMath for uint256; | ||
|
||
function curveToBDV(uint256 amount) external view returns (uint256) { | ||
return LibBeanMetaCurve.bdv(amount); | ||
} | ||
|
||
function lusdToBDV(uint256 amount) external view returns (uint256) { | ||
return LibBeanLUSDCurve.bdv(amount); | ||
} | ||
|
||
function bdv(address token, uint256 amount) external view returns (uint256) { | ||
if (token == C.beanAddress()) return amount.mul(1); | ||
else if (token == C.uniswapV2PairAddress()) return LibBeanEthUniswap.lpToLPBeans(amount); | ||
else if (token == C.curveMetapoolAddress()) return LibBeanMetaCurve.bdv(amount); | ||
else if (token == C.curveBeanLUSDAddress()) return LibBeanLUSDCurve.bdv(amount); | ||
revert("BDV: Token not whitelisted"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
pragma solidity ^0.7.6; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import {IBean} from "../../interfaces/IBean.sol"; | ||
|
||
/** | ||
* @author Publius | ||
* @title InitBip16 initializes BIP-16: It whitelists the Bean:LUSD Curve Plain Pool into the Silo and pays the publius address 5,000 Beans. | ||
**/ | ||
|
||
interface IBS { | ||
function whitelistToken(address token, bytes4 selector, uint32 stalk, uint32 seeds) external; | ||
function lusdToBDV(uint256 amount) external view returns (uint256); | ||
} | ||
|
||
contract InitBip16 { | ||
address private constant BEAN_ADDRESS = address(0xDC59ac4FeFa32293A95889Dc396682858d52e5Db); | ||
address private constant PUBLIUS_ADDRESS = address(0x925753106FCdB6D2f30C3db295328a0A1c5fD1D1); | ||
uint256 private constant PAYMENT = 5000000000; | ||
|
||
address private constant BEAN_LUSD_ADDRESS = address(0xD652c40fBb3f06d6B58Cb9aa9CFF063eE63d465D); | ||
uint32 private constant STALK = 10000; | ||
uint32 private constant SEEDS = 3; | ||
|
||
function init() external { | ||
IBS(address(this)).whitelistToken(BEAN_LUSD_ADDRESS, IBS.lusdToBDV.selector, STALK, SEEDS); | ||
IBean(BEAN_ADDRESS).mint(PUBLIUS_ADDRESS, PAYMENT); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma experimental ABIEncoderV2; | ||
pragma solidity ^0.7.6; | ||
|
||
interface ICurveMetapool { | ||
function A_precise() external view returns (uint256); | ||
function get_balances() external view returns (uint256[2] memory); | ||
function totalSupply() external view returns (uint256); | ||
function add_liquidity(uint256[] memory amounts, uint256 min_mint_amount) external returns (uint256); | ||
function remove_liquidity_one_coin(uint256 _token_amount, int128 i, uint256 min_amount) external returns (uint256); | ||
function balances(int128 i) external view returns (uint256); | ||
function fee() external view returns (uint256); | ||
function coins(uint256 i) external view returns (address); | ||
function get_virtual_price() external view returns (uint256); | ||
function calc_token_amount(uint256[] calldata amounts, bool deposit) external view returns (uint256); | ||
function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256); | ||
function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* SPDX-License-Identifier: MIT | ||
**/ | ||
|
||
pragma solidity ^0.7.6; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; | ||
import "./LibMetaCurve.sol"; | ||
|
||
interface IPlainCurve { | ||
function get_virtual_price() external view returns (uint256); | ||
} | ||
|
||
library LibBeanLUSDCurve { | ||
using SafeMath for uint256; | ||
|
||
uint256 private constant N_COINS = 2; | ||
uint256 private constant i = 0; | ||
uint256 private constant j = 1; | ||
|
||
address private constant BEAN_METAPOOL = 0x3a70DfA7d2262988064A2D051dd47521E43c9BdD; | ||
uint256 private constant BEAN_DECIMALS = 6; | ||
uint256 private constant BEAN_RM = 1e12; | ||
uint256 private constant I_BEAN_RM = 1e6; | ||
|
||
address private constant POOL = 0xD652c40fBb3f06d6B58Cb9aa9CFF063eE63d465D; | ||
address private constant TOKEN_METAPOOL = 0xEd279fDD11cA84bEef15AF5D39BB4d4bEE23F0cA; | ||
uint256 private constant TOKEN_DECIMALS = 18; | ||
|
||
function bdv(uint256 amount) internal view returns (uint256) { | ||
uint256 rate = getRate(); | ||
uint256 price = IPlainCurve(POOL).get_virtual_price(); | ||
if (rate < 1e18) price = price.mul(rate).div(1e18); | ||
return amount.mul(price).div(1e30); | ||
} | ||
|
||
function getRate() internal view returns (uint256 rate) { | ||
uint256 bean3CrvPrice = LibMetaCurve.price(BEAN_METAPOOL, BEAN_DECIMALS); | ||
uint256 token3CrvPrice = LibMetaCurve.price(TOKEN_METAPOOL, TOKEN_DECIMALS); | ||
rate = token3CrvPrice.mul(I_BEAN_RM).div( | ||
bean3CrvPrice | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* SPDX-License-Identifier: MIT | ||
**/ | ||
|
||
pragma solidity ^0.7.6; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; | ||
import "./LibMetaCurve.sol"; | ||
|
||
library LibBeanMetaCurve { | ||
using SafeMath for uint256; | ||
|
||
uint256 private constant A_PRECISION = 100; | ||
address private constant POOL = address(0x3a70DfA7d2262988064A2D051dd47521E43c9BdD); | ||
address private constant CRV3_POOL = address(0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7); | ||
uint256 private constant N_COINS = 2; | ||
uint256 private constant RATE_MULTIPLIER = 1e12; // Bean has 6 Decimals | ||
uint256 private constant PRECISION = 1e18; | ||
uint256 private constant i = 0; | ||
uint256 private constant j = 1; | ||
|
||
function bdv(uint256 amount) internal view returns (uint256) { | ||
// By using previous balances and the virtual price, we protect against flash loan | ||
uint256[2] memory balances = IMeta3Curve(POOL).get_previous_balances(); | ||
uint256 virtualPrice = IMeta3Curve(POOL).get_virtual_price(); | ||
uint256[2] memory xp = LibMetaCurve.getXP(balances, RATE_MULTIPLIER); | ||
uint256 a = IMeta3Curve(POOL).A_precise(); | ||
uint256 D = LibCurve.getD(xp, a); | ||
uint256 price = LibCurve.getPrice(xp, a, D, RATE_MULTIPLIER); | ||
uint256 totalSupply = D * PRECISION / virtualPrice; | ||
uint256 beanValue = balances[0].mul(amount).div(totalSupply); | ||
uint256 curveValue = xp[1].mul(amount).div(totalSupply).div(price); | ||
return beanValue.add(curveValue); | ||
} | ||
} |
Oops, something went wrong.