Skip to main content
Sigvex

Remediating Decimal Mismatch

How to normalize token decimal precision before arithmetic to prevent over/under-payment vulnerabilities.

Remediating Decimal Mismatch

Overview

Related Detector: Decimal Mismatch

Always normalize values to a common decimal base before performing arithmetic across different tokens or price feeds.

Before (Vulnerable)

function getValueInUsdc(uint256 ethAmount) public view returns (uint256) {
    (, int256 price,,,) = ethUsdFeed.latestRoundData(); // 8 decimals
    return ethAmount * uint256(price); // 18 + 8 = 26 decimals — not USDC's 6
}

After (Fixed)

function getValueInUsdc(uint256 ethAmount) public view returns (uint256) {
    (, int256 price,,,) = ethUsdFeed.latestRoundData(); // 8 decimals
    // Normalize: 18 (ETH) + 8 (price) - 6 (USDC) = 20 excess decimals
    return (ethAmount * uint256(price)) / 1e20;
}

Alternative Mitigations

  • Internal precision: Use a high-precision internal representation (e.g., 27 decimals like RAY in established fixed-point DeFi systems) and convert at boundaries.
  • Token decimals lookup: Query token.decimals() at initialization and store the scaling factor.

Common Mistakes

  • Hardcoding decimal assumptions: Assuming all tokens use 18 decimals. USDC/USDT use 6, WBTC uses 8.
  • Ignoring oracle decimals: off-chain aggregated feeds return 8 decimals for USD pairs but 18 for ETH pairs.

References