Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

Precision Loss in Slippage Calculation

Summary

The BaseAdapter calculates the minimum acceptable output (amountOutMin) for swaps using integer arithmetic. When expectedAmountOut (the estimated output of a trade) is very small, multiplying it by (1 - slippageToleranceBps) can result in precision loss, causing amountOutMin to round down to zero. This removes slippage protection entirely, allowing trades to execute even if the output is zero, which can be exploited by MEV bots or malicious actors.

Vulnerability Details

https://github.com/Cyfrin/2025-01-zaros-part-2/blob/35deb3e92b2a32cd304bf61d27e6071ef36e446d/src/utils/dex-adapters/BaseAdapter.sol#L128

Precision Loss:

When expectedAmountOut is small (e.g., 1 wei), amountOutMin can become zero due to integer division truncation. For example:

slippage tolerance of 1% (100 BPS) then If expectedAmountOut = 1 and slippageToleranceBps = 9999 (99.99% slippage):

amountOutMin = (1 * (10000 - 9999)) / 10000 = 1 / 10000 = 0

Impact

Users swapping small amounts lose their entire input due to zero slippage protection.

Tools Used

Manual review, Static analysis

Recommendations

Add a floor value to prevent amountOutMin from being zero or excessively small.

Scale calculations based on token decimals to handle small values (e.g., 1e6 for tokens with 18 decimals).

For example:

// In BaseAdapter.sol
uint256 public constant MIN_SWAP_OUT = 1e6; // 0.000001 tokens (18 decimals)
function calculateAmountOutMin(uint256 expectedAmountOut) internal view returns (uint256) {
// Calculate with slippage tolerance
uint256 amountOutMin = (expectedAmountOut * (Constants.BPS_DENOMINATOR - slippageToleranceBps))
/ Constants.BPS_DENOMINATOR;
// Enforce minimum output to prevent precision loss
if (amountOutMin < MIN_SWAP_OUT) {
revert Errors.SlippageTooHigh(amountOutMin, MIN_SWAP_OUT);
}
return amountOutMin;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.