Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

endless-c - Incorrect Decimal Handling in MixOracle Price Calculation #1019

Open
sherlock-admin2 opened this issue Nov 25, 2024 · 0 comments

Comments

@sherlock-admin2
Copy link

sherlock-admin2 commented Nov 25, 2024

endless-c

Medium

Incorrect Decimal Handling in MixOracle Price Calculation

Summary

The incorrect decimal handling in MixOracle.sol will cause significant price discrepancies as the contract fails to properly scale token decimals when calculating prices from Tarot Oracle TWAP and Pyth oracle feeds, which leads to severely undervalued or overvalued asset prices.

Root Cause

In MixOracle.sol#L40-L95, the getThePrice function incorrectly handles decimals in multiple places:

  1. When calculating amountOfAttached:
int amountOfAttached = int(
    (((2 ** 112)) * (10 ** decimalsToken1)) / twapPrice112x112
);
  1. When calculating the final price:
uint price = (uint(amountOfAttached) * uint(attachedTokenPrice)) /
    (10 ** decimalsToken1);

The calculation fails to properly account for:

  • The scaling factor (2^112) from Tarot Oracle
  • The different decimal places between token0 and token1
  • The additional scaling applied by Tarot Oracle (10^12)

Internal pre-conditions

No response

External pre-conditions

  1. Tarot Oracle needs to return a TWAP price for a token pair with different decimals (e.g., WETH/USDT with 18/6 decimals)
  2. The price ratio between tokens needs to be significant enough to make the decimal scaling error apparent
  3. The Pyth oracle price feed for the attached token needs to be active and returning prices

Attack Path

No response

Impact

Medium. The incorrect decimal handling leads to wrong price calculations that could significantly impact protocol operations relying on these price feeds.

PoC

Consider a WETH/USDT pair where:

  • WETH (token0): 18 decimals
  • USDT (token1): 6 decimals
  • Pool reserves: 100 WETH and 300,000 USDT

As demonstrated in the Python POC:

def getPrice_USDT():
    nt0 = 100  # token 0 (WETH) reserves
    nt1 = 300000  # token 1 (USDT) reserves
    nt0_decimal = 10**18
    nt1_decimal = 10**6
    
    twapPrice112x112 = (nt1 * nt1_decimal) * 2**112 / nt0 * nt0_decimal 
    
    amount_of_attached = (2**112 * 10**6) / ((nt1 * nt1_decimal) * 2**112 / nt0 * nt0_decimal)
    amount_of_attached = nt0 * 10**18 / nt1  # Simplified after cancellation
    
    attachedTokenPrice = 3000 
    decimalsToken1 = 6
    price = (amount_of_attached) * attachedTokenPrice / (10**decimalsToken1)
    
    print(f"more human readable price: {price /10**8}$")

This shows that the current implementation:

  1. Incorrectly cancels out the 2^112 scaling
  2. Doesn't properly handle the decimal difference between token0 and token1
  3. Results in a significantly wrong price due to improper scaling

Mitigation

Modify the price calculation in getThePrice to properly handle decimals

@sherlock-admin3 sherlock-admin3 changed the title Little Spruce Seagull - Incorrect Decimal Handling in MixOracle Price Calculation endless-c - Incorrect Decimal Handling in MixOracle Price Calculation Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant