Sablier

Sablier
DeFiFoundry
53,440 USDC
View results
Submission Details
Severity: low
Invalid

Leading Zeros and Significant Digits Issue in stringifyFractionalAmount Function

Summary

The stringifyFractionalAmount function converts a fractional amount to a string, but it does not ensure a consistent number of decimal places or handle trailing zeros appropriately. Here’s the original implementation:

function stringifyFractionalAmount(uint256 fractionalAmount) internal pure returns (string memory) {
// Return the empty string if the fractional amount is zero.
if (fractionalAmount == 0) {
return "";
}
// Add a leading zero if the fractional part is less than 10, e.g., for "1", this function returns ".01".
else if (fractionalAmount < 10) {
return string.concat(".0", fractionalAmount.toString());
}
// Otherwise, stringify the fractional amount simply.
else {
return string.concat(".", fractionalAmount.toString());
}
}

Proof of concept

Scenario: The function is called with various fractional amounts to generate string representations.
Example Inputs and Outputs:
Input: 1 → Output: .01 (correct)
Input: 10 → Output: .10 (correct, but trailing zero might be unnecessary)
Input: 99 → Output: .99 (correct)
Input: 100 → Output: .100 (incorrect, as it should not handle values >= 100)

Impact

  1. The function may produce inconsistent string representations for fractional amounts, leading to potential confusion or misinterpretation.

  2. Lack of handling for trailing zeros and ensuring a consistent number of decimal places can result in incorrect or unexpected formatting.

  3. Users might see inconsistent or incorrect representations of fractional amounts, leading to confusion and mistrust.

Tools Used

Manual review

Recommendations

Here is a revised implementation of the stringifyFractionalAmount function that includes configurable precision and standardized formatting:

function stringifyFractionalAmount(uint256 fractionalAmount, uint256 precision) internal pure returns (string memory) {
// Return the empty string if the fractional amount is zero.
if (fractionalAmount == 0) {
return "";
}
// Convert the fractional amount to a string.
string memory fractionalString = fractionalAmount.toString();
// Ensure the fractional string is padded to the desired precision.
while (bytes(fractionalString).length < precision) {
fractionalString = string.concat(fractionalString, "0");
}
// Truncate the fractional string to the desired precision.
if (bytes(fractionalString).length > precision) {
fractionalString = substring(fractionalString, 0, precision);
}
// Concatenate the dot and the fractional string.
return string.concat(".", fractionalString);
}
// Helper function to get a substring.
function substring(string memory str, uint256 startIndex, uint256 endIndex) internal pure returns (string memory) {
bytes memory strBytes = bytes(str);
bytes memory result = new bytes(endIndex - startIndex);
for (uint256 i = startIndex; i < endIndex; i++) {
result[i - startIndex] = strBytes[i];
}
return string(result);
}

Explanation of the Enhanced Implementation

  1. The function now accepts an additional precision parameter, allowing it to handle varying levels of decimal precision. This ensures flexibility in formatting different fractional amounts.

  2. The function ensures that the fractional string is padded with trailing zeros to match the specified precision. It also truncates the string if it exceeds the desired precision, ensuring consistent formatting.

  3. The substring helper function allows for extracting a portion of the string, ensuring that the fractional part is truncated to the specified precision if necessary.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Info/Gas/Invalid as per Docs

https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.