Divide Before Multiply
Detects arithmetic expressions where division precedes multiplication, causing precision loss from integer truncation.
Divide Before Multiply
Overview
The divide-before-multiply detector identifies arithmetic expressions where a division operation is performed before a multiplication, causing unnecessary precision loss. In Solidity’s integer arithmetic, division truncates toward zero. When the truncated result is subsequently multiplied, the rounding error is amplified. Reordering the operations to multiply first preserves precision.
Why This Is an Issue
Consider (a / b) * c versus (a * c) / b. If a = 7, b = 3, c = 2: the first evaluates to (2) * 2 = 4, while the second evaluates to 14 / 3 = 4. But with a = 5, b = 3, c = 2: the first gives (1) * 2 = 2, while the second gives 10 / 3 = 3. The error compounds in DeFi protocols processing large numbers of transactions, leading to systematic value extraction or accumulated losses.
How to Resolve
// Before: Vulnerable — division before multiplication
uint256 reward = (totalReward / totalStaked) * userStake;
// Loses precision: if totalReward = 999, totalStaked = 1000, result = 0
// After: Fixed — multiply first
uint256 reward = (totalReward * userStake) / totalStaked;
// Preserves precision: result = 999 * userStake / 1000
When multiplication-first risks overflow, use a mulDiv function:
uint256 reward = Math.mulDiv(totalReward, userStake, totalStaked);
Detection Methodology
- Division instruction identification: Locates DIV and SDIV opcodes in the bytecode.
- Result tracking: Traces the division result forward to check if it feeds into a subsequent MUL.
- Reordering safety check: Verifies whether reordering to multiply-first would risk overflow (in which case a mulDiv helper is recommended instead).
- Constant analysis: Filters out divisions by powers of 2 (which are bit shifts) and trivial cases.
Limitations
False positives: Intentional rounding-down-then-multiply patterns (e.g., computing per-share values that should be truncated) may be flagged. False negatives: Divide-before-multiply patterns split across multiple functions or temporaries may not be detected.
Related Detectors
- Precision Errors — detects precision loss broadly
- Integer Overflow — detects arithmetic overflow