OracleFacet Manual Review Findings

OracleFacet Manual Review Findings

OFT-01M: Incorrect Price Evaluation

Description:

The price evaluation of BEAN and USDC that is exposed by the getTWAPPrices function of OracleFacet is incorrect as it validates the pair's index only in the beanPrice calculation and additionally does not factor in the newly added reserve (1e6) to the denominator akin to the UniswapV2Library.

Example:

protocol/contracts/farm/facets/OracleFacet.sol
87function getTWAPPrices() public view returns (uint256, uint256) {
88 if (s.o.timestamp == 0) return (1e18, 1e18);
89 (uint256 price0Cumulative, uint256 price1Cumulative, uint32 blockTimestamp) =
90 UniswapV2OracleLibrary.currentCumulativePrices(s.c.pair);
91 (uint256 peg_priceCumulative,, uint32 peg_blockTimestamp) =
92 UniswapV2OracleLibrary.currentCumulativePrices(s.c.pegPair);
93 uint256 priceCumulative = s.index == 0 ? price0Cumulative : price1Cumulative;
94
95 uint32 timeElapsed = blockTimestamp - s.o.timestamp; // overflow is desired
96 uint32 pegTimeElapsed = peg_blockTimestamp - s.o.pegTimestamp; // overflow is desired
97
98 uint256 beanPrice;
99 uint256 usdcPrice;
100 if (timeElapsed > 0) {
101 uint256 price1 = (priceCumulative - s.o.cumulative) / timeElapsed / 1e12;
102 beanPrice = Decimal.ratio(price1, 2**112).mul(1e18).asUint256();
103 } else {
104 (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(s.c.pair).getReserves();
105 beanPrice = (s.index == 0 ? 1e6 * reserve1 / reserve0 : 1e6 * reserve0 / reserve1);
106 }
107 if (pegTimeElapsed > 0) {
108 uint256 price2 = (peg_priceCumulative - s.o.pegCumulative) / pegTimeElapsed / 1e12;
109 usdcPrice = Decimal.ratio(price2, 2**112).mul(1e18).asUint256();
110 } else {
111 (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(s.c.pegPair).getReserves();
112 usdcPrice = 1e6 * reserve1 / reserve0;
113 }
114 return (beanPrice, usdcPrice);
115}

Recommendation:

We advise the calculation to be corrected or the inaccuracy to be reflected in documentation above the function to prevent potential mis-integration of external projects and off-chain services.

Alleviation:

After extensive discussion with the Beanstalk team, we concluded that the code performs as intended given that the 1e6 offset yields proper prices and that the index at the latter of the two highlighted lines is assumed to be 0 as indicated by a newly introduced comment. As a result, we consider this exhibit nullified.

Navigated to OracleFacet Manual Review Findings