sherlock-audit / 2024-10-axion

3 stars 4 forks source link

Division by Zero Vulnerability in SolidlyV2AMO.sol Leading to Denial of Service #2

Open CipherHawk0 opened 1 month ago

CipherHawk0 commented 1 month ago

Summary

The missing zero-check on boostReserve in the _validateSwap function will cause a division by zero error for users, as an attacker can manipulate the BOOST-USD liquidity pool to set boostReserve to zero and trigger the error, resulting in a denial of service.

Root Cause

In SolidlyV2AMO.sol, the _validateSwap function lacks a zero-check on boostReserve before performing division, leading to a potential division by zero error.

Relevant Code Snippet: function _validateSwap(bool boostForUsd) internal view override { (uint256 boostReserve, uint256 usdReserve) = getReserves(); if (boostForUsd && boostReserve >= usdReserve) revert InvalidReserveRatio({ratio: (FACTOR usdReserve) / boostReserve}); if (!boostForUsd && usdReserve >= boostReserve) revert InvalidReserveRatio({ratio: (FACTOR usdReserve) / boostReserve}); }

Internal pre-conditions

1.The boostReserve variable in the BOOST-USD pool is zero.

External pre-conditions

1.An attacker manipulates the BOOST-USD liquidity pool to reduce boostReserve to zero by swapping out all BOOST tokens.

Attack Path

1.Attacker swaps all BOOST tokens out of the BOOST-USD pool, setting boostReserve to zero. 2.User calls the mintSellFarm or unfarmBuyBurn function. 3.The function internally calls _validateSwap, which attempts to compute (FACTOR * usdReserve) / boostReserve. 4,Since boostReserve is zero, a division by zero error occurs, causing the transaction to revert. 5.As a result, users cannot execute critical AMO functions, leading to a denial of service.

Impact

The users cannot execute mintSellFarm and unfarmBuyBurn functions, leading to a denial of service in maintaining the BOOST token's peg. The protocol's ability to perform AMO operations is hindered until the issue is resolved.

PoC

To demonstrate the vulnerability, follow these steps:

1.Setup: Deploy the SolidlyV2AMO contract with appropriate parameters. Ensure the BOOST-USD pool exists and is connected to the contract.

2.Manipulate Pool Reserves: An attacker uses a large amount of USD tokens to swap for all available BOOST tokens in the pool. This action drains BOOST tokens from the pool, setting boostReserve to zero.

3.Trigger the Vulnerability: -A user calls the mintSellFarm function: solidlyV2AMO.mintSellFarm();

-The function internally calls _validateSwap, which then calls getReserves: (uint256 boostReserve, uint256 usdReserve) = getReserves();

-Since boostReserve is zero, the following division causes a division by zero error: (FACTOR * usdReserve) / boostReserve

4.Result: The transaction reverts due to the division by zero. The user is unable to perform the intended AMO operation.

Mitigation

-->Add a zero-check for boostReserve in the _validateSwap function to prevent division by zero:

function _validateSwap(bool boostForUsd) internal view override { (uint256 boostReserve, uint256 usdReserve) = getReserves(); if (boostReserve == 0) revert InvalidReserveRatio({ratio: 0}); if (boostForUsd && boostReserve >= usdReserve) revert InvalidReserveRatio({ratio: (FACTOR usdReserve) / boostReserve}); if (!boostForUsd && usdReserve >= boostReserve) revert InvalidReserveRatio({ratio: (FACTOR usdReserve) / boostReserve}); }

-->Explanation: -By checking if boostReserve is zero and reverting early, we prevent the division by zero error. -The InvalidReserveRatio error is emitted with a ratio of zero for clarity.

-->Additional Recommendations: 1.Validate Reserves: Ensure both boostReserve and usdReserve are non-zero before performing operations dependent on them.

2.Mitigate Pool Manipulation: -Implement mechanisms to prevent or reduce the impact of pool reserve manipulation, such as using time-weighted average prices (TWAP). -Use robust oracle systems to fetch reserve data.

3.Enhance Error Handling: -Provide descriptive error messages to aid in debugging and monitoring. -Consider emitting events when critical conditions like zero reserves are detected.

-->By implementing the recommended fix and additional safeguards, the contract can prevent this issue and maintain reliable AMO operations.

mz8t commented 1 month ago

The initial condition is not valid: the Boost reserve cannot be zero since we are using xyz-type pools ( xyz pools are native in v2, and for the version/audit we are using full-range pools in v3 )

Extending the AMO to finite ranges actually requires more tools!