mul_div() uses calculations that prevent overflow/underflow, which can cause problems in various places and not following the purpose of the original FullMath.mulDiv.
It first does the multiplication via widening_mul() and then the division inside the unsafe block. But the widening_mul() implementation does not allow overflow.
Even the fact that the division is in a unsafe block, the multiplication will not be able to overflow, which is not the case in the original Uniswap's FullMath library:
An overflow is expected there, and the entire operation is in the unchecked block:
*/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits*
mul_div is used a lot in the protocol and this bug can block many of the math operations - here are some examples where mul_div is used:
swap()
position update
all functions in sqrt_price_math()
The math in all these cases should also be in unchecked blocks, but the fix in mul_div will fix that, since this is the actual math operation, the same applies for mul_div_rounding_up.
Lines of code
https://github.com/code-423n4/2024-08-superposition/blob/4528c9d2dbe1550d2660dac903a8246076044905/pkg/seawater/src/maths/full_math.rs#L32-L51
Vulnerability details
Impact
mul_div()
uses calculations that preventoverflow
/underflow
, which can cause problems in various places and not following the purpose of the originalFullMath.mulDiv
.Proof of Concept
The
mul_div()
is performinga * b / c
:full_math.rs#L32-L51
It first does the multiplication via
widening_mul()
and then the division inside the unsafe block. But thewidening_mul()
implementation does not allow overflow.https://docs.rs/alloy-primitives/0.7.6/alloy_primitives/aliases/type.U256.html#method.widening_mul
Even the fact that the division is in a
unsafe
block, the multiplication will not be able tooverflow
, which is not the case in the originalUniswap
'sFullMath
library:An overflow is expected there, and the entire operation is in the unchecked block:
https://github.com/Uniswap/v3-core/blob/6562c52e8f75f0c10f9deaf44861847585fc8129/contracts/libraries/FullMath.sol#L5-L6
https://github.com/Uniswap/v3-core/blob/6562c52e8f75f0c10f9deaf44861847585fc8129/contracts/libraries/FullMath.sol#L19
mul_div
is used a lot in the protocol and this bug can block many of the math operations - here are some examples wheremul_div
is used:swap()
sqrt_price_math()
The math in all these cases should also be in unchecked blocks, but the fix in
mul_div
will fix that, since this is the actual math operation, the same applies formul_div_rounding_up
.Tools Used
Manual Review & The same problem was found here - https://github.com/sherlock-audit/2023-01-uxd-judging/issues/273
Recommended Mitigation Steps
Wrap the entire function inside
unchecked
/unsafe
block, like theUniswap
0.8 implementation - https://github.com/Uniswap/v3-core/blob/0.8/contracts/libraries/FullMath.sol#L14-L19Assessed type
Math