Algo Ssstablecoinsss

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

Hardcoded 18-Decimal Scaling Causes 10-Order-of-Magnitude WBTC Collateral Undervaluation & Broken Liquidation Seizures

[H-01] Hardcoded 18-Decimal Scaling Causes 10-Order-of-Magnitude WBTC Collateral Undervaluation & Broken Liquidation Seizures

Summary

The dsc_engine.vy contract hardcodes precision scaling constants (PRECISION = 10**18 and ADDITIONAL_FEED_PRECISION = 10**10) across all collateral conversion functions. On ZKsync Era and Ethereum, Wrapped Bitcoin (WBTC) uses 8 decimals. This hardcoded assumption undervalues deposited WBTC by a factor of $10^{10}$ ($10 \text{ billion times}$), blocking users from borrowing against WBTC, and causes liquidation transfers to fail due to attempting to seize $10^{18}$ WBTC tokens.

Vulnerability Details

In src/dsc_engine.vy, token valuation functions assume all tokens have 18 decimals and all price feeds have 8 decimals ($18 - 8 = 10$):

# Lines 76-78
PRECISION: constant(uint256) = 10**18
ADDITIONAL_FEED_PRECISION: constant(uint256) = 10**10
FEED_PRECISION: constant(uint256) = 10**8

In _get_usd_value():

# Lines 280-284
return (
(convert(price, uint256) * ADDITIONAL_FEED_PRECISION) * amount
) // PRECISION

When a user deposits $1 \text{ WBTC}$ ($10^8$ satoshis) with WBTC price at $60,000 ($60,000 \times 10^8$):
$$
The actual collateral value is $60,000 ($60000 \times 10^{18}$ wei). The protocol records the value as , preventing the user from minting even 1 DSC token.

In _get_token_amount_from_usd():

# Lines 305-309
return (usd_amount_in_wei * PRECISION) // (
(convert(price, uint256)) * ADDITIONAL_FEED_PRECISION
)

When calculating collateral to seize for $60,000 of debt ($60,000 \times 10^{18}$ wei):
$$
The contract calculates $10^{18}$ WBTC tokens ($10 \text{ billion WBTC}$), far exceeding WBTC total supply (21 million). Any attempt by a liquidator to liquidate a WBTC position reverts in the ERC20 transfer.

Impact

  • Severe Loss of Functionality: WBTC collateral is practically unusable; depositors cannot mint DSC.

  • Protocol Insolvency: Any existing WBTC positions can never be liquidated, leaving bad debt unrecoverable.

Proof of Concept

An automated test is included in tests/unit/test_poc_audit.py:

mox test tests/unit/test_poc_audit.py -k test_poc_wbtc_8decimals_collateral_distortion

The test deposits $1 \text{ WBTC}$, checks that get_account_collateral_value returns only , confirms that minting 1 DSC reverts with DSCEngine__BreaksHealthFactor, and verifies that get_token_amount_from_usd calculates $10^{18}$ tokens instead of $10^8$.

Tools Used

  • Moccasin v0.4.4

  • Titanoboa v0.2.8

  • Pytest

Recommended Mitigation

Dynamically query decimals from the collateral token or pass scaling factors in constructor:

+interface IERC20Metadata:
+ def decimals() -> uint8: view
@internal
@view
def _get_usd_value(token: address, amount: uint256) -> uint256:
price_feed: AggregatorV3Interface = AggregatorV3Interface(self.s_price_feeds[token])
price: int256 = price_feed.stale_check_latest_round_data()
+ token_decimals: uint256 = convert(staticcall IERC20Metadata(token).decimals(), uint256)
+ return (convert(price, uint256) * 10**10 * amount) // (10**token_decimals)
Updates

Lead Judging Commences

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