Skip to content

Bug: _toQuadruplePrecisionInt skips rounding for negative numbers #765

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions