Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Valid

Guaranteed Runtime Failure for Negative Values in Fixed-Point Conversion

Summary

The convertSd59x18ToTokenAmount() function in the Collateral library contains a critical design flaw that causes guaranteed runtime failures when processing negative values due to an improper unsigned conversion.

The current code design guarantees runtime failures for negative values. The function attempts to convert SD59x18 (signed fixed-point) numbers to token amounts using intoUint256(), which explicitly reverts on negative inputs:

// From PRBMath implementation
function intoUint256(SD59x18 x) pure returns (uint256 result) {
int256 xInt = SD59x18.unwrap(x);
if (xInt < 0) {
revert CastingErrors.PRBMath_SD59x18_IntoUint256_Underflow(x);
}
result = uint256(xInt);
}

This creates a mathematical domain violation as the function's input type (SD59x18) supports the full range of signed values, but the conversion path forcibly restricts this to non-negative values only. This restriction breaks the system's ability to process legitimate negative values in financial calculations.

The issue is particularly severe because proper conversion paths exist within PRBMath for handling signed-to-unsigned conversions, but they're not being utilized. Instead, the code attempts an unsafe conversion that PRBMath explicitly prevents through runtime checks.

Impact

The impact of this flaw creates a systemic failure in the protocol's financial calculations. Since PRBMath's intoUint256() explicitly reverts on negative values, all negative numerical flows in the system will fail at runtime. This prevents handling of essential financial operations like debt positions, penalties, and price adjustments that naturally involve negative values. Protocol developers are forced to implement fragmented workarounds outside the standard conversion path, increasing complexity and risk of errors in financial calculations.

Recommendation

The implementation should be modified to maintain signed value support throughout the conversion process:

function convertSd59x18ToTokenAmount(
Data storage self,
SD59x18 amountX18
) internal view returns (int256) {
return Math.convertSd59x18ToTokenAmount(self.decimals, amountX18);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

When totalAssetsMinusVaultDebtX18 is negative `convertSd59x18ToTokenAmount` reverts, making `getVaultCreditCapacity` revert, making a couple of core functions revert

Support

FAQs

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