PriceFeed
does not account for the exponent of the base price
#495
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
insufficient quality report
This report is not of sufficient quality
🤖_primary
AI based primary recommendation
🤖_10_group
AI based duplicate group recommendation
Lines of code
https://github.com/code-423n4/2024-05-predy/blob/main/src/PriceFeed.sol#L45-L58
https://github.com/code-423n4/2024-05-predy/blob/main/src/vendors/IPyth.sol#L5-L14
https://github.com/code-423n4/2024-05-predy/blob/main/src/libraries/PositionCalculator.sol#L142-L144
Vulnerability details
Impact
The protocol utilizes
getPriceNoOlderThan
from thePyth
oracle to determine the price of thebase token
, which is subsequently used to calculate thesqrtPrice
.The
Pyth
oracle returns aPrice struct
that contains theprice
andexponent
.The protocol does not take into account the
exponent
returned and proceeds to utilize theprice
without theexponent
for thesqrt price
calculation, therefore thesqrt price
will be incorrect.This will impact any calls to
PriceFeed::getSqrtPrice()
. An example is to check if positions are liquidatable if they are unsafe, if thesqrt price
is incorrect, then safe positions may be liquidated or unsafe positions may be unable to be liquidated.Proof of Concept
PriceFeed.sol#L45-L58
The
IPyth.Price
struct contains the following parameters:IPyth.sol#L5-L14
As mentioned in the Pyth Network Docs:
"The returned price and confidence are decimal numbers written in the form a * 10^e, where e is an exponent included in the result. For example, a price of 1234 with an exponent of -2 represents the number 12.34. The result also includes a publishTime which is the unix timestamp for the price update."
This means that the exponent must be applied to the
basePrice.price
to get the actual price. MostPyth Oracles
return a negative exponent, but it's possible that it may be positive, so both cases need to be handled.Currently, the protocol uses the returned
basePrice.price
for thesqrtPrice
calculation, which will return an incorrectsqrtPrice
.An example of where this price feed is used is in
PositionCalculator::getSqrtIndexPrice
PositionCalculator.sol#L142-L144
The flow of the call in this example is
LiquidationLogic::liquidate
=>LiquidationLogic::checkVaultIsDanger
=>PositionCalculator::isLiquidatable
=>PositionCalculator::calculateMinMargin
=>PositionCalculator::getSqrtIndexPrice
In that case, this would not correctly be able to determine if a position is unsafe and should be forced liquidated.
Tools Used
Manual Review
Recommended Mitigation Steps
Apply the returned
expo
of thePrice struct
to theprice
. Theexpo
may be positive or negative, so both cases must be handled. If exponent is negative, ensure to negate it when dividing.Assessed type
Oracle
The text was updated successfully, but these errors were encountered: