Algo Ssstablecoinsss

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

Precision loss in calculation

Root + Impact

Integer division in price conversions and health factor calculations truncates fractional values, causing users to lose dust amounts that accumulate over many operations and can be exploited through repeated small transactions.

Description

  • The protocol converts between token amounts and USD values using integer division with 18-decimal precision, calculating collateral values and health factors for all operations.

  • Integer division rounds down (truncates), causing precision loss on every conversion, where small amounts lose proportionally more value and repeated operations accumulate losses.

# dsc_engine.vy line 313-315
@internal
@view
def _get_usd_value(token: address, amount: uint256) -> uint256:
# ... get price ...
return (
(convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount
) // PRECISION # @> Division truncates, loses fractional wei
# dsc_engine.vy line 325-327
@internal
@pure
def _calculate_health_factor(total_dsc_minted: uint256, collateral_value_in_usd: uint256) -> uint256:
collateral_adjusted_for_threshold: uint256 = (
collateral_value_in_usd * LIQUIDATION_THRESHOLD
) // LIQUIDATION_PRECISION # @> Division truncates
return (collateral_adjusted_for_threshold * (10**18)) // total_dsc_minted # @> Division truncates
# dsc_engine.vy line 362-365
@internal
@view
def _get_token_amount_from_usd(token: address, usd_amount_in_wei: uint256) -> uint256:
# ... get price ...
return (
(usd_amount_in_wei * PRECISION) // (
convert(price, uint256) * ADDITIONAL_FEED_PRECISION
)
) # @> Division truncates

Risk

Likelihood:

  • Every price conversion and health factor calculation performs integer division, affecting all deposits, mints, redeems, and liquidations.

  • Users performing many small transactions accumulate more precision loss than single large transactions for the same total amount.

Impact:

  • Small amounts round to lower values, users lose dust on every operation (e.g., 999 wei becomes 0 after conversion).

  • Attackers exploit by performing thousands of tiny operations to extract accumulated truncated amounts favoring protocol or themselves.

Proof of Concept

# Example 1: Dust loss on small amounts
tiny_eth = 100 # 100 wei
usd_value = dsce.get_usd_value(weth, tiny_eth) # Might round to 0
# If price = $2000, 100 wei * 2000 * 1e10 / 1e18 = 0.002 → rounds to 0
# Example 2: Accumulated loss from repeated operations
total_loss = 0
for i in range(1000):
# Each small operation loses fractional value
deposited = 1000 * 1e18 + 999 # 1000.000000000000000999 ETH
usd_val = dsce.get_usd_value(weth, deposited)
eth_back = dsce.get_token_amount_from_usd(weth, usd_val)
loss = deposited - eth_back # Lost 999 wei per operation
total_loss += loss
# After 1000 operations: Lost ~999,000 wei total
# Example 3: Health factor rounding benefits user
# Collateral: $100,000.999, Debt: $50,000
# Adjusted: 100,000.999 * 50 / 100 = 50,000.4995 → rounds to 50,000
# HF: 50,000 * 1e18 / 50,000 = 1.0 (but should be slightly less)
# User appears healthier than reality

Recommended Mitigation

# dsc_engine.vy
+MIN_COLLATERAL_AMOUNT: constant(uint256) = 1000 # Minimum 1000 wei
+MIN_DSC_AMOUNT: constant(uint256) = 1 * 10**18 # Minimum 1 DSC
@internal
def _deposit_collateral(token_collateral_address: address, amount_collateral: uint256):
- assert amount_collateral > 0, "DSCEngine_NeedsMoreThanZero"
+ assert amount_collateral >= MIN_COLLATERAL_AMOUNT, "DSCEngine_AmountTooSmall"
# ... rest of function
@internal
def _mint_dsc(amount_dsc_to_mint: uint256):
- assert amount_dsc_to_mint > 0, "DSCEngine__NeedsMoreThanZero"
+ assert amount_dsc_to_mint >= MIN_DSC_AMOUNT, "DSCEngine_AmountTooSmall"
# ... rest of function
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 3 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!