High
In src/dsc_engine.vy, collateral is valued in USD with:
ADDITIONAL_FEED_PRECISION is 1e10 and PRECISION is 1e18. This is correct only when amount has 18 decimals (WETH).
The same pattern is used in _get_token_amount_from_usd. The engine never reads token decimals(), and FEED_PRECISION is unused.
The contest targets ZKsync Era with WETH and WBTC. On that chain, WETH is 18 decimals and WBTC is 8 decimals. One WBTC (amount = 1e8) is valued about 1e10 times too low compared to the intended USD price.
_get_token_amount_from_usd is inverted the same way, so liquidation and redeem sizing for WBTC are also wrong.
Impact: High. WBTC deposits are almost worthless in accounting. Users cannot mint a fair amount of DSC against WBTC. Health factor, mint limits, and liquidation amounts for WBTC are incorrect. Any non-18-decimal collateral in a fork breaks the same way.
Likelihood: High on the documented WETH + WBTC / ZKsync path.
Engine math (same as _get_usd_value):
At health factor 1, max DSC is about half of reported collateral USD, so roughly 3e-6 DSC per 1 WBTC instead of about 30000 DSC.
Live decimals on ZKsync (addresses from moccasin.toml):
Normalize each collateral amount to 18 decimals before the price formula, and reverse that scale in _get_token_amount_from_usd. Store decimals at init or read IERC20Detailed(token).decimals().
Add unit tests with 8-decimal collateral (WBTC shape), not only 18-decimal mocks.
## Description The `_revert_if_health_factor_is_broken` function is responsible for ensuring that a user's health factor meets the minimum required standard. There is only implementation for WETH. ## Vulnerability Details In the function, there is only implementation for WETH. ```Solidity @internal def _revert_if_health_factor_is_broken(user: address): user_health_factor: uint256 = self._health_factor(user) assert ( user_health_factor >= MIN_HEALTH_FACTOR ), "DSCEngine__BreaksHealthFactor" ``` Value of the `MIN_HEALTH_FACTOR=10^18`is higher than the Satoshi factor which is 10^8. As a result, for WBTC, the `user_health_factor` can be inflated to more than 101010^{10} times its normal value. ## Impact Bigger value of MIN_HEALTH_FACTOR for WBTC allows on bigger value of `user_health_factor`and wrong value when function should revert. ## Recommendations Add MIN_HEALTH_FACTOR also for WBTC. ```Solidity @internal def _revert_if_health_factor_is_broken(user: address): user_health_factor: uint256 = self._health_factor(user) # Check if the user's token is WBTC and adjust health factor accordingly if user_health_factor >= (MIN_HEALTH_FACTOR * 10**10): # If user health factor is higher due to WBTC precision, still ensure it meets the minimum assert user_health_factor >= MIN_HEALTH_FACTOR, "DSCEngine__BreaksHealthFactor" else: assert user_health_factor >= MIN_HEALTH_FACTOR, "DSCEngine__BreaksHealthFactor" ```
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.