_get_usd_value and _get_token_amount_from_usd convert between token amounts and USD using fixed precision constants that assume every collateral amount is denominated in 18 decimals. The protocol's stated collateral set is WETH (18 decimals) and WBTC, which has 8 decimals. For WBTC the USD value of a deposit is understated by a factor of 10^10, and the token amount computed for a given USD debt is overstated by the same factor. The repository's own mocks hide this because both mock collateral tokens are (incorrectly) built with 18 decimals.
In src/dsc_engine.vy:
Neither function ever queries the token's actual decimals(). With a $60,000 BTC price (feed answer 60000 * 10**8):
get_usd_value(wbtc, 10**8) (1 WBTC in real units) returns 6,000,000,000,000 instead of 60,000 * 10**18 — the position is counted as $0.000006.
get_token_amount_from_usd(wbtc, 60_000 * 10**18) returns 10^18 units — i.e. 10,000,000,000 WBTC in 8-decimal terms — for a position that holds 10^8 units.
Two concrete failures against the real WBTC token:
WBTC is unusable as borrowing collateral. $60,000 of deposited WBTC has a counted adjusted value of 3 * 1012 wei, so minting even 1 DSC reverts with DSCEngine__BreaksHealthFactor; the maximum mintable amount against 1 WBTC is exactly 3 * 1012 wei of DSC (0.000003 DSC).
WBTC positions can never be liquidated. liquidate computes the seize amount via _get_token_amount_from_usd, obtaining 1018 units for $60,000 of debt coverage, then _redeem_collateral tries to subtract that from a deposited balance denominated in 108-scale units and underflows, reverting the whole liquidation. Any DSC debt that is (also) backed by WBTC cannot be seized through the WBTC leg.
Boa/pytest test using an 8-decimal WBTC mock (passes locally):
Read each collateral token's decimals() (cache it at registration) and normalize amounts to 18 decimals inside _get_usd_value and _get_token_amount_from_usd before applying the feed precision — e.g. scale by 10 ** (18 - token_decimals) on the way in and the inverse on the way out. Add a test with a real 8-decimal WBTC mock; the current 18-decimal mocks mask the bug.
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.