Skip to content

Latest commit

 

History

History
47 lines (26 loc) · 2.22 KB

File metadata and controls

47 lines (26 loc) · 2.22 KB

Little Olive Yeti

High

Pyth expo value is not handled correctly.

Summary

The expo value returned by Pyth oracles is related to the decimals of the returned price. Currently, the implementation always assumes expo is negative. However, if expo is positive, the protocol will fail to fetch the price correctly.

Root Cause

If expo is positive, then this line will incorrectly calculate the decimals due to overflow.

Internal Pre-conditions

None needed

External Pre-conditions

  1. Pyth oracle expo value is positive

Attack Path

As stated in the official Pyth network docs, the expo value returned from the getPriceUnsafe function represents the decimal precision of the returned price. This expo value can be either negative or positive.

If the returned expo is negative, the following line in PythOracle.sol:151 will get an extra big value because converting negative values to uint will start from the last bit.

Impact

The protocol will fail to fetch the price due to unsafe casting from int to uint, causing the function to revert due to "0" price. This can be especially problematic during periods of high market activity when price updates are critical. If the admin doesn’t act quickly to change the oracle address, some liquidations may be delayed, potentially resulting in bad debt.

Previous issue found from the same root cause: sherlock-audit/2023-07-perennial-judging#56

PoC

If the expo returned from getPriceUnsafe is 1, casting it as uint32(-1) will result in 2^32 - 1, which is an extremely large value. Consequently, the scale will also be a massive number, and the scaledPrice will evaluate to 0, causing the price to be incorrectly reported.

uint256 scale = 10 ** (feedDecimals + decimals - PRICE_SCALE);
scaledPrice = price / scale;

Mitigation

No response