Severity: Medium
The constructor allows storeFrontPriceFactor == FACTOR_SCALE (only rejects >), and asset packing does not validate liquidationFactor, so 0 is accepted.
With this combination:
discountFactor = FACTOR_SCALE * (1e18 - 0) / 1e18 = FACTOR_SCALE
assetPriceDiscounted = assetPrice * (1e18 - 1e18) / 1e18 = 0
Every quoteCollateral() and buyCollateral() call then reverts on division by zero. Since config is immutable, this permanently disables collateral sales for that market.
// Constructor — equality allowed
if (config.storeFrontPriceFactor > FACTOR_SCALE) revert BadDiscount();
// quoteCollateral — divides by assetPriceDiscounted which is 0
uint256 discountFactor = mulFactor(storeFrontPriceFactor, FACTOR_SCALE - assetInfo.liquidationFactor);
uint256 assetPriceDiscounted = mulFactor(assetPrice, FACTOR_SCALE - discountFactor);
return basePrice * baseAmount * assetInfo.scale / assetPriceDiscounted / baseScale;
Recommendation: Use >= in the constructor check and add a runtime guard:
if (config.storeFrontPriceFactor >= FACTOR_SCALE) revert BadDiscount();
// ...
if (assetPriceDiscounted == 0) revert BadPrice();
— whitedog
Severity: Medium
The constructor allows
storeFrontPriceFactor == FACTOR_SCALE(only rejects>), and asset packing does not validateliquidationFactor, so0is accepted.With this combination:
discountFactor = FACTOR_SCALE * (1e18 - 0) / 1e18 = FACTOR_SCALEassetPriceDiscounted = assetPrice * (1e18 - 1e18) / 1e18 = 0Every
quoteCollateral()andbuyCollateral()call then reverts on division by zero. Since config is immutable, this permanently disables collateral sales for that market.Recommendation: Use
>=in the constructor check and add a runtime guard:— whitedog