The updateReserve function is responsible for calculating the step size to update the reserve value based on the target price and the current price. It uses the difference between the pd.lutData.highPrice and pd.lutData.lowPrice to determine the step size.
If the pd.lutData.highPrice and pd.lutData.lowPrice are equal, this means the target price is exactly between the high and low prices in the lookup table. In this case, the expression (pd.lutData.highPrice - pd.lutData.lowPrice) will be zero, which will lead to a division by zero error when calculating the step size.
Code
function updateReserve(PriceData memory pd, uint256 reserve) internal pure returns (uint256) {
if (pd.targetPrice > pd.currentPrice) {
// if the targetPrice is greater than the currentPrice,
// the reserve needs to be decremented to increase currentPrice.
return reserve
- pd.maxStepSize * (pd.targetPrice - pd.currentPrice) / (pd.lutData.highPrice - pd.lutData.lowPrice);
} else {
// if the targetPrice is less than the currentPrice,
// the reserve needs to be incremented to decrease currentPrice.
return reserve
+ pd.maxStepSize * (pd.currentPrice - pd.targetPrice) / (pd.lutData.highPrice - pd.lutData.lowPrice);
}
}
Impact
If the updateReserve function encounters a division by zero error, it will revert the entire transaction, preventing the function from successfully executing. This can have significant consequences, as the calcReserveAtRatioSwap and calcReserveAtRatioLiquidity functions rely on the updateReserve function to converge on the correct reserve value.
If the updateReserve function fails, the calling functions will not be able to properly calculate the reserve values, which could lead to incorrect pricing, swaps, or liquidity calculations.
This issue could potentially affect the overall functionality and reliability of the Stable2 contract, especially in cases where the target price is close to the midpoint between the high and low prices in the lookup table.
Poc
function testUpdateReserveWithHighAndLowPriceEqual() public {
Stable2.PriceData memory pd;
pd.lutData.highPrice = 1_000_000;
pd.lutData.lowPrice = 1_000_000;
pd.targetPrice = 1_000_000;
pd.currentPrice = 999_999;
pd.maxStepSize = 1_000;
uint256 updatedReserve = stable2.updateReserve(pd, 10_000);
assertEq(updatedReserve, 9_000, "Reserve should be decremented by the full step size");
pd.targetPrice = 1_000_001;
pd.currentPrice = 1_000_000;
updatedReserve = stable2.updateReserve(pd, 10_000);
assertEq(updatedReserve, 11_000, "Reserve should be incremented by the full step size");
}
Mitigation
Add a check to handle the case where the high and low prices are equal.
Lines of code
https://github.com/code-423n4/2024-07-basin/blob/7d5aacbb144d0ba0bc358dfde6e0cc913d25310e/src/functions/Stable2.sol#L387
Vulnerability details
Vulnerability Details
The
updateReserve
function is responsible for calculating the step size to update the reserve value based on the target price and the current price. It uses the difference between thepd.lutData.highPrice
andpd.lutData.lowPrice
to determine the step size.If the
pd.lutData.highPrice
andpd.lutData.lowPrice
are equal, this means the target price is exactly between the high and low prices in the lookup table. In this case, the expression(pd.lutData.highPrice - pd.lutData.lowPrice)
will be zero, which will lead to a division by zero error when calculating the step size.Code
Impact
If the
updateReserve
function encounters a division by zero error, it will revert the entire transaction, preventing the function from successfully executing. This can have significant consequences, as thecalcReserveAtRatioSwap
andcalcReserveAtRatioLiquidity
functions rely on theupdateReserve
function to converge on the correct reserve value.If the
updateReserve
function fails, the calling functions will not be able to properly calculate the reserve values, which could lead to incorrect pricing, swaps, or liquidity calculations.This issue could potentially affect the overall functionality and reliability of the Stable2 contract, especially in cases where the target price is close to the midpoint between the high and low prices in the lookup table.
Poc
Mitigation
Add a check to handle the case where the high and low prices are equal.
Assessed type
Math