BIP-38: Migrate urBEAN3CRV to urBEANETH

Proposed: October 13, 2023

Status: Passed

Link: Snapshot


Proposer

Beanstalk Farms, Brendan Sanderson, Ben Weintraub

Proposer Wallet: 0x87c5e5413d60e1419fd70b17c6d299aa107efb49

Summary

Problem

As of writing, over 98% of liquidity for Beans is currently in the BEAN3CRV pool.

BEAN3CRV:

Beanstalk currently does not support multiple Unripe LP tokens.

BDV that has not been migrated to Silo V3 is not included in s.siloBalances[token].depositedBdv. For Beanstalk to support a Grown Stalk Gauge System, it is necessary to track the total Deposited BDV for each whitelisted token.

Proposed Solution

Migration Process

Migrate the BEAN3CRV LP tokens that underly the urBEAN3CRV token to BEANETH Well LP tokens. In doing so, the liquidity underlying urBEAN3CRV is migrated to the BEANETH Well and the urBEAN3CRV token becomes the urBEANETH token (albeit, with the same token address).

Perform the following actions by the Beanstalk Community Multisig (BCM):

Transaction # Protocol Description
1 Beanstalk Execute BIP-38 Diamond Cut and transfer underlying BEAN3CRV to the BCM
2 Curve Remove BEAN3CRV liquidity as Bean, USDC, USDT and DAI proportionate to the ratio of the pool
3a CoW Swap Upgrade Safe to support CoW Swap TWAP + swap USDC into ETH using TWAP order
3b CoW Swap Swap USDT into ETH using TWAP order
3c CoW Swap Swap DAI into ETH using TWAP order
4 Basin Add Beans from Step (2) and ETH from Step (3) as liquidity to the BEANETH Well
5 Beanstalk Add BEANETH LP as underlying token for the new urBEANETH

In order to minimize the risk of the swap being frontrun (for example, immediately after the passage of the BIP), authorize the BCM to begin the migration process at any point within 30 days of the passage of this BIP.

During the migration process, attempts to Deposit, Convert or Chop Unripe assets will revert. After the migration process is complete, Conversions between urBEAN and urBEANETH will Convert in/out of the BEANETH Well instead of the BEAN3CRV pool.

The cost of slippage during Step (3) is passed onto the Unripe LP holders.

addMigratedUnderlying is added to the Unripe Facet to migrate the underlying token of an Unripe token to a new token.

Due to the multi-step nature of this BIP, BCM Signers are only expected to submit Etherscan verified messages for the initial Diamond Cut transaction.

Fertilizer Changes

Upgrade the Barn to add liquidity to the BEANETH Well instead of the BEAN3CRV pool upon each Fertilizer purchase.

As a result:

Silo V3 Unmigrated BDV

A two step process is required to start properly tracking the total Deposited BDV of each whitelisted token. Implement the first step by adding a counter (s.migratedBdvs) that tracks the amount of BDV that has been migrated to Silo V3 for each token.

In the second step, the total Deposited BDV for each token is incremented by the remaining unmigrated BDV at the BIP-38 commitment block subtracted by the BDV that has been migrated since that block as stored on-chain. This second step must be implemented in a future BIP.

Technical Rationale

Given that the migration process cannot be executed atomically and Unripe asset functionality will be in a broken state during it, attempts to Deposit, Convert or Chop Unripe assets during the migration process will revert.

The Unripe Facet must be updated to add support for migrating the Unripe LP token to a new underlying asset.

The mintFertilizer function must be updated to include the minFertilizerOut parameter to account for potential movement in the ETH price between transaction submission and execution. The addFertilizerOwner function is removed given that it would need to be updated to reflect the migration to urBEANETH, however it was only expected to be called once during the Replant.

The Convert Facet and Convert Getters Facet must be updated due to function changes in LibUnripeConvert.sol and LibWellConvert.sol.

The Metadata Facet must be updated in order to update the ERC-1155 metadata for urBEANETH Deposits.

The BDV Facet must be updated due to unripeLPToBDV being changed to reflect the migration to BEANETH.

The Migration Facet must be updated due to the introduction of the migrated BDV counter.

Economic Rationale

Beans primarily trade against 3CRV which is a significant centralization vector for Beanstalk. Ether is the most decentralized, censorship resistant and liquid asset on the Ethereum network.

For as long as most liquidity for Beans is in the BEAN3CRV pool, Beanstalk is still subject to inter-block MEV manipulation. The Multi Flow Pump on the BEANETH Well is the first Ethereum-native oracle for Ethereum-native data that offers inter-block MEV manipulation resistance in a post-Merge environment.

For as long as most volume for Beans is in the BEAN3CRV pool, most trades with Beans are still subject to an unnecessary trading fee in the pool, which results in worse prices for Farmers and worse peg maintenance for Beanstalk. The Constant Product 2 Well Function used by the BEANETH Well has no trading fee.

The price of 3CRV is dependent on the worst of the prices of USDC, USDT and DAI. ETH is not subject to the same risk.

Contract Changes

Initialization Contract

The init function on the following InitMigrateUnripeBean3CrvToBeanEth contract is called:

Unripe Facet

The following UnripeFacet is removed from Beanstalk:

The following UnripeFacet is added to Beanstalk:

UnripeFacet Function Changes

Name Selector Action Type New Functionality
_getPenalizedUnderlying 0xa84643e4 Replace View
balanceOfPenalizedUnderlying 0x1acc0a47 Replace View
balanceOfUnderlying 0x1acc0a47 Replace View
getPenalizedUnderlying 0x6de45df2 Replace View
getPenalty 0x014a8a49 Replace View
getPercentPenalty 0xbb7de478 Replace View
getRecapFundedPercent 0x43cc4ee0 Replace View
getRecapPaidPercent 0xab434eb7 Replace View
getTotalUnderlying 0xadef4533 Replace View
getUnderlying 0x9f06b3fa Replace View
getUnderlyingPerUnripeToken 0xb8a04d1b Replace View
getUnderlyingToken 0x691bcc88 Replace View
isUnripe 0xfc6a19df Replace View
picked 0xd3c73ec8 Replace View
addMigratedUnderlying 0x787cee99 Add Call
addUnripeToken 0xfa345569 Replace Call
chop 0x9a516cad Replace Call
pick 0x13ed3cea Replace Call
switchUnderlyingToken 0xa33fa99f Add Call

Fertilizer Facet

The following FertilizerFacet is removed from Beanstalk:

The following FertilizerFacet is added to Beanstalk:

FertilizerFacet Function Changes

Name Selector Action Type New Functionality
balanceOfBatchFertilizer 0x304ec65d Replace View
balanceOfFertilized 0xb6f42085 Replace View
balanceOfFertilizer 0x1799b3b2 Replace View
balanceOfUnfertilized 0x1edb6be1 Replace View
beansPerFertilizer 0x9bb4e35a Replace View
getActiveFertilizer 0xdc6ba285 Replace View
getCurrentHumidity 0x39448802 Replace View
getEndBpf 0xc85951a1 Replace View
getFertilizer 0x9c45a1d5 Replace View
getFertilizers 0x34af5416 Replace View
getFirst 0x1e223143 Replace View
getHumidity 0x29130a66 Replace View
getLast 0x4d622831 Replace View
getMintFertilizerOut 0x69744dd0 Add View
getNext 0xf4a057e2 Replace View
isFertilizing 0x6ae1c014 Replace View
remainingRecapitalization 0x4a16607c Replace View
totalFertilizedBeans 0x4f9a9678 Replace View
totalFertilizerBeans 0xf9c4ebde Replace View
totalUnfertilizedBeans 0xa3ef48c9 Replace View
addFertilizerOwner 0x8cd31ca0 Remove Call
claimFertilized 0x83e08888 Replace Call
mintFertilizer 0x0bfca7e3 Remove Call
mintFertilizer 0xbb02e10b Add Call
payFertilizer 0xd47aee59 Replace Call

Convert Facet

The following ConvertFacet is removed from Beanstalk:

The following ConvertFacet is added to Beanstalk:

ConvertFacet Function Changes

Name Selector Action Type New Functionality
convert 0xb362a6e8 Replace Call

Convert Getters Facet

The following ConvertGettersFacet is removed from Beanstalk:

The following ConvertGettersFacet is added to Beanstalk:

ConvertGettersFacet Function Changes

Name Selector Action Type New Functionality
getAmountOut 0x4aa06652 Replace View
getMaxAmountIn 0x24dd285c Replace View

Metadata Facet

The following MetadataFacet is removed from Beanstalk:

The following MetadataFacet is added to Beanstalk:

MetadataFacet Function Changes

Name Selector Action Type New Functionality
imageURI 0xc20b8071 Replace View
name 0x06fdde03 Replace View
symbol 0x95d89b41 Replace View
uri 0x0e89341c Replace View

BDV Facet

The following BDVFacet is removed from Beanstalk:

The following BDVFacet is added to Beanstalk:

BDVFacet Function Changes

Name Selector Action Type New Functionality
beanToBDV 0x5a049a47 Replace View
curveToBDV 0xf984019b Replace View
unripeBeanToBDV 0xc8cda2a0 Replace View
unripeLPToBDV 0xb0c22bb1 Replace View
wellBdv 0xc84c7727 Replace View

Migration Facet

The following MigrationFacet is removed from Beanstalk:

The following MigrationFacet is added to Beanstalk:

MigrationFacet Function Changes

Name Selector Action Type New Functionality
balanceOfGrownStalkUpToStemsDeployment 0x505f43ea Replace View
balanceOfLegacySeeds 0x1be2cfd8 Replace View
getDepositLegacy 0xa9be1acb Replace View
mowAndMigrate 0x1f4f3d55 Replace Call
mowAndMigrateNoDeposits 0xaed942e9 Replace Call
totalMigratedBdv 0x2b8cde0d Add View

Event Changes

Name Change
SwitchUnderlyingToken New event

Beans Minted

None.

Audit

The commit hash of this BIP is 76066733bcddb944b9af8f29acf150c02a5b8437.

Cyfrin has performed an audit of commit hash 12c608a22535e3a1fe379db1153185fe43851ea7 and then reviewed remediations included in commit hash 76066733bcddb944b9af8f29acf150c02a5b8437.

The final audit report can be found here.

Effective

No upgrades are necessarily executed by the BCM immediately upon the passage of this BIP.

The BCM has up to 30 days after the passage of this BIP to start the migration outlined in Migration Process.