# `StableOracleDAI` calculates `getPriceUSD` with inverted base/rate tokens for Chainlink price

StableOracleDAI averages a WETH/DAI Uniswap quote with a DAI/ETH Chainlink feed, inverting the ratio and inflating USSD minted per DAI deposited.

- Payout: Contest reward
- Severity: high
- Program: USSD
- Credited: 0xPkhatri
- Disclosed: 2023-05-15
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-05-USSD-judging/issues/102
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-05-USSD%3AH-1
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:oracle-manipulation

**Target:** StableOracleDAI price oracle (Chainlink feed + Uniswap V3 TWAP)
**Root cause:** Chainlink priceFeedDAIETH returns DAI/ETH while the Uniswap quoteSpecificPoolsWithTimePeriod call uses WETH as base and DAI as quote (WETH/DAI); the two are averaged without inverting one, so the ratio is wrong.
**Steps:**
1. Read StableOracleDAI constructor: priceFeedDAIETH = 0x773616E4d11A78F511299002da57A0a94577F1f4, which is the DAI/ETH Chainlink feed.
2. Read getPrice(): DAIEthOracle.quoteSpecificPoolsWithTimePeriod(1e18, WETH, DAI, pools, 600) returns WETH/DAI (base=WETH, quote=DAI).
3. Observe getPriceUSD computes wethPriceUSD*1e18 / ((DAIWethPrice + price*1e10)/2), averaging a WETH/DAI value with a DAI/ETH value.
4. Call USSD.mintForToken() with DAI; the inflated getPriceUSD yields far more USSD than deserved.
5. Also observe USSDRebalancer.rebalance() consumes the same broken price for its trades.
**How found:** Code reading of the oracle: noticed the misleading comment claiming WETH/USD 8 decimals, checked the Chainlink feed address on Etherscan/docs to confirm it is DAI/ETH, and compared against the Uniswap quote's base/quote ordering (WETH base, DAI quote).
**Exploitation:** Any user calls mintForToken() with DAI; the mispriced oracle returns an inflated DAI price, minting excess USSD and diluting the stablecoin. Rebalancer trades also execute at wrong values.
**Insight:** When an oracle averages a DEX quote with a Chainlink feed, verify each source's base/quote orientation independently (feed address on Etherscan, pool token0/token1 ordering) rather than trusting variable names or comments like DAIWethPrice.
