init()
will fail because the well that should be whitelisted has no liquidityHigh Risk
https://github.com/Cyfrin/2024-04-beanstalk-2/blob/27ff8c87c9164c1fbff054be5f22e56f86cdf127/protocol/contracts/libraries/Well/LibWellBdv.sol#L37-L39
According to the team “the initial liquidity for the new Bean-wstEth well will be added to the well once the Eth from the old well is converted to wstEth”. The problem is that it will not be possible to initiate the migration to the new well because the init()
function will revert if the new well does not have any liquidity in it.
When calling InitMigrateUnripeBeanEthToBeanSteth:init()
to initiate the migration from the Bean-ETH well to the Bean-wstETH well, the new well is whitelisted by calling LibWhitelist:whitelistToken()
. During this function call the function LibWellBdv:bdv
is entered:
function bdv(
address well,
uint amount
) internal view returns (uint _bdv) {
uint beanIndex = LibWell.getBeanIndexFromWell(well);
// For now, assume Beanstalk should always use the first pump and given that the Well has been whitelisted, it should be assumed
// that the first Pump has been verified when the Well was whitelisted.
Call[] memory pumps = IWell(well).pumps();
uint[] memory reserves = IInstantaneousPump(pumps[0].target).readInstantaneousReserves(well, pumps[0].data);
// If the Bean reserve is beneath the minimum balance, the oracle should be considered as off.
require(reserves[beanIndex] >= C.WELL_MINIMUM_BEAN_BALANCE, "Silo: Well Bean balance below min");
Call memory wellFunction = IWell(well).wellFunction();
uint lpTokenSupplyBefore = IWellFunction(wellFunction.target).calcLpTokenSupply(reserves, wellFunction.data);
reserves[beanIndex] = reserves[beanIndex].sub(BEAN_UNIT); // remove one Bean
uint deltaLPTokenSupply = lpTokenSupplyBefore.sub(
IWellFunction(wellFunction.target).calcLpTokenSupply(reserves, wellFunction.data)
);
_bdv = amount.mul(BEAN_UNIT).div(deltaLPTokenSupply);
}
This function gets the reserves of the new Bean-wstETH well that should be whitelisted and checks if the bean reserves of the well are >= WELL_MINIMUM_BEAN_BALANCE
which is set to 1000 beans:
uint[] memory reserves = IInstantaneousPump(pumps[0].target).readInstantaneousReserves(well, pumps[0].data);
// If the Bean reserve is beneath the minimum balance, the oracle should be considered as off.
require(reserves[beanIndex] >= C.WELL_MINIMUM_BEAN_BALANCE, "Silo: Well Bean balance
uint256 internal constant WELL_MINIMUM_BEAN_BALANCE = 1000_000_000; // 1,000 Beans
The issue arises from the fact that at the time the well is whitelisted it does not have any liquidity in it because according to the development team “the initial liquidity will be added to the well once the Eth is converted to wstEth”. This means the function will revert and therefore it will not be possible to initiate the migration.
Do not whitelist the well when calling InitMigrateUnripeBeanEthToBeanSteth:init()
but add a second function InitMigrateUnripeBeanEthToBeanSteth:finish()
where the LP tokens for the new well are added and the new well which now has enough liquidity is whitelisted.