Incorrect use of library comparison function
Description
The _decimal_div
function uses the is_le
function to compare the number of decimals between the numerator and the denominator. The specification of the is_le
function states that it returns 1 when the first argument is less than or equal to the second argument:
// Returns 1 if a <= b (or more precisely 0 <= b - a < RANGE_CHECK_BOUND).
// Returns 0 otherwise.
@known_ap_change
func is_le{range_check_ptr}(a, b) -> felt {
return is_nn(b - a);
}
The implementation of _decimal_div
assumes otherwise. The is_le
function will return TRUE
if b_decimals <= a_decimals
or a_decimals >= b_decimals
. This is different from the code below, which assumes that the two numbers can only be equal in the else branch.
let b_fewer_dec = is_le(b_decimals, a_decimals);
if (b_fewer_dec == TRUE) {
// x > y
a_to_shift = a_value;
result_decimals = a_decimals;
tempvar range_check_ptr = range_check_ptr;
} else {
// x <= y
As a result, the case when the two numbers are equal is handled by the first if branch instead of the else branch as expected by the code.
Impact
The correctness of the _decimal_div
function is not affected by the incorrect usage of the is_le
function as the code for handling the first if branch and the equality leads to the same outcome.
However, this same mistake may show up in other places, and such assumptions should be carefully verified before using them in code.
Recommendations
Rearrange the if conditions so that the case of equality is handled by the if branch rather than the else branch.
Remediation
The issue was addressed in a later update.