Skip to content

Bug: _toQuadruplePrecisionInt skips rounding for negative numbers #765

@Mavline

Description

@Mavline

Description

In contracts/libraries/math/InterestRates.sol, the function _toQuadruplePrecisionInt (line 86-95) has a rounding bug for negative inputs.

Code

function _toQuadruplePrecisionInt(int256 number, int256 decimals) private pure returns (bytes16) {
    if (number % decimals > 0) {  // <-- never true for negative numbers
        number += 1;
    }
    bytes16 nominator = ABDKMathQuad.fromInt(number);
    bytes16 denominator = ABDKMathQuad.fromInt(decimals);
    bytes16 fraction = ABDKMathQuad.div(nominator, denominator);
    return fraction;
}

Problem

In Solidity, the modulo operator preserves the sign of the dividend. For negative number:

  • (-7) % 3 == -1 (not 2)
  • Since -1 > 0 is false, the number += 1 rounding is skipped

The unsigned version _toQuadruplePrecision (line 73-83) works correctly because uint256 % uint256 is always non-negative.

Impact

When negative values pass through _toQuadruplePrecisionInt, they miss the rounding adjustment that the unsigned version applies. The difference is approximately 1/decimals per call (dust-level), but it creates an asymmetry between positive and negative interest calculations.

Suggested Fix

function _toQuadruplePrecisionInt(int256 number, int256 decimals) private pure returns (bytes16) {
    if (number % decimals != 0) {
        number += 1;
    }
    // ...
}

Or for direction-aware rounding:

int256 remainder = number % decimals;
if (remainder > 0) {
    number += 1;
} else if (remainder < 0) {
    number -= 1;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions