Submitted by Egis_Security
The Basin team has implemented look up table to fetch pre-calculated values, which are close to the targetPrice to decrease the complexity of calcReserveAtRatioSwap and calcReserveAtRatioLiquidity functions.
Stable2LUT1 has a function getRatiosFromPriceSwap, which returns PriceData struct based on provided price.
We can see that in case of super extreme price, the function will revert with LUT: Invalid price, but there is also support for extreme prices, which we assume should work correctly, when such situation occurs.
We will investigate an edge case, which is present when we enter if (price < 0.213318e6) and price is above 0.001083e6. In such situations, the function will return the following struct:
If you notice, we have a large gap between highPrice and lowPrice and more precisely. The following results in large jump in reserves calculation when updateReserve which leads to skipping the target price sequentially, which moves away pd.currentPrice until we exit the for loop, which returns 0.
Here is an estimation of the impact based on the PoC which is below:
For a ratio ~ 1:4.6 of the price of the tokens:
Place the following test inside /test/beanstalk/BeanstalkStable2.calcReserveAtRatioLiquidity.t.sol and run it with forge test --mt "test_calcReserveAtRatioSwapSkipTarget" -vv:
You can further add console.log inside the for loop of calcReserveAtRatioSwap and log pd.currentPrice on each update. Notice that each time, the current price is further away from the target. Here are logs:
Fuzz Testing
Recalculate the PriceData for the given case and consider narrowing down the price diff.
Invalid Validation
Brean0 (Basin) confirmed
0xsomeone (judge) decreased severity to Low and commented:
nmirchev8 (warden) commented:
nickkatsios (Basin) commented:
0xsomeone (judge) increased severity to Medium and commented:
