Skip to main content
Sigvex

Divide Before Multiply Remediation

How to avoid precision loss in integer math by ordering operations to multiply before dividing.

Divide Before Multiply Remediation

Overview

Related Detector: Divide Before Multiply

EVM integer division truncates toward zero. When a formula divides before it multiplies, the truncated intermediate loses precision that the later multiplication then scales up, producing a result that is systematically too small — sometimes zero. In fee, reward, and share-price math this is a real value leak. The remediation is to reorder so multiplication happens first, or to use a full-precision mulDiv.

Before (Vulnerable)

// reward = (amount / totalStaked) * rewardPool
// If amount < totalStaked, (amount / totalStaked) truncates to 0 and reward is 0.
function reward(uint256 amount, uint256 totalStaked, uint256 rewardPool)
    external pure returns (uint256)
{
    return (amount / totalStaked) * rewardPool;
}

After (Fixed — multiply first)

// reward = (amount * rewardPool) / totalStaked
// The division happens last, so the intermediate keeps full precision.
function reward(uint256 amount, uint256 totalStaked, uint256 rewardPool)
    external pure returns (uint256)
{
    return (amount * rewardPool) / totalStaked;
}

When the numerator amount * rewardPool could itself overflow 256 bits, use a full-precision helper such as OpenZeppelin’s Math.mulDiv(amount, rewardPool, totalStaked), which computes a * b / c without an intermediate overflow.

Common Mistakes

  • Fixing one formula but leaving the same pattern in a sibling function (e.g. deposit fixed, withdraw not).
  • Reordering to multiply first and introducing an overflow the earlier division was masking; reach for mulDiv when operands are large.
  • Scaling by a fixed-point factor (1e18) after dividing, which does not recover the already-lost precision.

References