Algo Ssstablecoinsss

AI First Flight #2
Beginner FriendlyDeFi
EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Non-18-decimals collateral token breaks USD valuation (e.g. USDC=6), mispricing the health factor and causing insolvency

Non-18-decimals collateral token breaks USD valuation, leading to mispriced health factors and insolvency

Description

_get_usd_value hardcodes ADDITIONAL_FEED_PRECISION = 1e10 and divides by PRECISION = 1e18, which only produces a correct USD value when the collateral token has exactly 18 decimals and the feed has 8. Any collateral with a different number of decimals (e.g. USDC/USDT = 6, WBTC = 8) is valued off by orders of magnitude.

# dsc_engine.vy:314-316 (_get_usd_value)
return (
(convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount # @> assumes amount is 1e18-scaled
) // PRECISION

The protocol registers exactly two collateral tokens in the constructor with no per-token decimals lookup, so a 6-decimals token's amount is 1e12x too small and the position is valued at ~one-millionth of its real worth.

Risk

Likelihood:
High. Stablecoin engines are routinely deployed with USDC/WBTC-style collateral, and the constructor accepts any two token addresses. The First Flight's own setup uses standard tokens.

Impact:
High. Mispricing flows directly into _calculate_health_factor. A 6-decimals collateral is undervalued, so a depositor cannot mint against real value and a tiny price move triggers unfair liquidation; conversely a token with >18 decimals is overvalued, letting a user mint DSC far beyond their collateral and leaving the protocol undercollateralized / insolvent.

Proof of Concept

Deploy the engine with a 6-decimals collateral feed at $1; deposit 1000e6 (=$1000) and call get_account_collateral_value.

# 1000 USDC = 1000e6 units, price=1e8, ADDITIONAL_FEED_PRECISION=1e10
# value = (1e8 * 1e10 * 1000e6) // 1e18 = 1e9 wei = $0.000000001 (should be $1000)
assert engine.get_account_collateral_value(user) == 1000 * 10**18 # FAILS, returns 1e9

Recommended Mitigation

Normalize every collateral amount to 18 decimals using the token's decimals() before valuation.

- return (
- (convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount
- ) // PRECISION
+ decimals: uint8 = staticcall IERC20Detailed(token).decimals()
+ normalized_amount: uint256 = amount * 10**(18 - convert(decimals, uint256))
+ return (
+ (convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * normalized_amount
+ ) // PRECISION
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 5 hours ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!