Algo Ssstablecoinsss

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

[M-01] Implicit Precision Assumptions in Oracle and Collateral Handling Can Break Solvency Calculations

Root + Impact

Description

  • The protocol defines fixed precision constants:

FEED_PRECISION = 1e8
ADDITIONAL_FEED_PRECISION = 1e10
PRECISION = 1e18

USD value calculation:

(convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount // PRECISION

However:

  • The contract does not call price_feed.decimals()

  • The contract does not normalize ERC20(token).decimals()

This implicitly assumes:

  • Oracle price feeds use 8 decimals

  • Collateral tokens use 18 decimals

If either assumption is violated:

  • Collateral value becomes miscomputed

  • Health factor becomes inaccurate

  • Liquidation eligibility may be incorrectly determined

  • Mint limits may be exceeded

The solvency model is therefore tightly coupled to implicit precision alignment rather than dynamically enforcing it.

Risk

Technical Risk

Collateral valuation depends on fixed scaling factors instead of querying external contract configuration dynamically.

Likelihood: Medium

  • Reason 1 Adding new collateral tokens (e.g., 6-decimal tokens like USDC)

  • Reason 2 Integrating price feeds with non-8 decimal precision

  • Reason 3 Expanding protocol support across chains with different oracle configurations

Impact: Medium

Incorrect collateral valuation may occur if a price feed or collateral token uses non-standard decimals. Since mint limits and liquidation thresholds rely directly on USD valuation, mispricing can distort:

  • Impact 1 Maximum mintable DSC

  • Impact 2 Health factor calculation

  • Impact 3 Liquidation eligibility


    This can lead to:

  • Undercollateralized positions not being liquidated

  • Safe positions being liquidated incorrectly

  • Stablecoin supply exceeding intended collateral backing


    Because the stablecoin’s solvency model depends entirely on correct valuation, this introduces economic risk.

Proof of Concept

Deploy two engines:

  • Engine A → 8-decimal feed

  • Engine B → 18-decimal feed

With identical human prices.

with boa.reverts():
engine_ok.mint_dsc(over_mint)
engine_bad.mint_dsc(over_mint)

Engine with incorrect feed precision allows excessive minting.

Recommended Mitigation

The protocol should remove implicit precision assumptions and normalize values dynamically.

1.Normalize Oracle Price Precision

The issue originates from hardcoded precision constants used inside the USD valuation logic:

(convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount // PRECISION

This logic assumes:

  • Feed decimals = 8

  • Token decimals = 18

Instead, valuation should dynamically normalize both price and token precision.

2.This logic assumes:

  • In get_usd_value(token, amount):

    AggregatorV3Interface(self.token_address_to_price_feed[token]).decimals() and ERC20(token).decimals()
  • Normalize both price and amount to 18 decimals.

  • Compute USD value using only 1e18 precision.

price_feed: AggregatorV3Interface = AggregatorV3Interface(self.token_address_to_price_feed[token])
feed_decimals: uint256 = price_feed.decimals()
token_decimals: uint256 = ERC20(token).decimals()
# price is int256 from oracle_lib
normalized_price: uint256 = convert(price, uint256) * 10**(18 - feed_decimals)
normalized_amount: uint256 = amount * 10**(18 - token_decimals)
usd_value: uint256 = (normalized_price * normalized_amount) // 10**18

3.Remove Hardcoded Precision Constants

Eliminate:

FEED_PRECISION
ADDITIONAL_FEED_PRECISION

They are no longer required when normalization is dynamic.

4.Apply Same Normalization in Reverse Conversion Function

The function converting USD → token amount must also normalize feed precision dynamically:

token_amount = (usd_amount * 10**feed_decimals) // raw_price

Failing to update both directions will reintroduce precision drift.

5.Enforce Precision Invariant at Deployment

To prevent misconfiguration:

assert price_feed.decimals() <= 18, "Unsupported feed precision"

1.In get_token_amount_from_usd(token, usd_amount):

  • Use the same feed_decimals and token_decimals

  • Invert the normalized formula so both directions remain consistent.

price_feed: AggregatorV3Interface = AggregatorV3Interface(self.token_address_to_price_feed[token])
feed_decimals: uint256 = price_feed.decimals()
token_decimals: uint256 = ERC20(token).decimals()
normalized_price: uint256 = convert(price, uint256) * 10**(18 - feed_decimals)
# returns token units (token_decimals)
token_amount: uint256 = (usd_amount * 10**18 // normalized_price) // 10**(18 - token_decimals)

This removes reliance on FEED_PRECISION / ADDITIONAL_FEED_PRECISION and prevents mispricing when adding feeds/tokens with non-default decimals.

Conclusion:

The protocol’s solvency model relies on implicit decimal assumptions rather than dynamically enforcing precision consistency.

While current deployment may operate under aligned precision, future integrations or asset expansions could introduce systemic valuation errors.

This warrants Medium severity due to its potential impact on collateral accounting and liquidation correctness.

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!