Contests
Active
Upcoming
Juging Contests
Escalations Open
Sherlock Judging
Finished
Source: https://github.com/sherlock-audit/2024-12-mach-finance-judging/issues/41
0xRiO, 0xc0ffEE, 0xpetern, bbl4de, c3phas, d4y1ight, eeyore, fuzzysquirrel, miaowu, silver_eth, vahdrak1, zanderbyte, zxriptor
The Pyth integration contract uses the getPriceUnsafe()
function to retrieve the latest reported price from a specified price feed.
However, Pyth does not have sponsored price feeds on the Sonic chain, that will guaranty the proper data freshness. As such, this function depends on users or the Mach protocol to update the price data with fresh values.
As a result, the prices retrieved using getPriceUnsafe()
can be significantly outdated, even with the protocol best efforts to maintain price freshness due to its keeper/bot outages.
The documentation for getPriceUnsafe()
incorrectly suggests that it will revert with a StalePrice
error when the price is outdated. In reality, this function returns a price with its associated timestamp, regardless of how old the timestamp is, as long as the price was updated at some point in the past.
This issue becomes critical if the prices used by the protocol are not updated for extended periods, during which significant price changes could occur for assets being borrowed or used as collateral in the project.
The Pyth integration contract does not perform a staleness check, and did not switch to fallback oracle in such situation. It only verifies that the price is > 0 (here), which is insufficient.
Although Compound V2 does not enforce staleness checks in its Chainlink oracle integration, the situation differs because Chainlink prices cannot be updated directly by anyone. Even stale prices from Chainlink are deemed acceptable under these circumstances, especially to avoid blocking liquidations.
In contrast, Pyth allows anyone to update the price feed (via updatePriceFeeds()
function), in situation where the new price adheres to the rule that it must be newer than the previous price and is a valid Pyth price component for given price feed.
This introduces a vulnerability where price updates can be manipulated to extract value from users.
None.
An attacker can construct a transaction that updates the price feed with a desired value reported at a timestamp between the last update and the current time. This enables the attacker to inflate the price of borrowed assets and deflate the price of collateral assets, leading to forced liquidations.
The reported prices can originate from any valid price component with timestamp within the allowed timeframe. As observed in real-world scenarios, asset prices can rise by 10% in one day and fall by 20% on another day (e.g., FTM).
Consider a three-day timeframe during which Pyth prices for two supported assets are not updated:
The attacker can then update:
This manipulation allows the attacker to extract maximum liquidable value from users, profiting from the actual prices of the assets.
This attack would not be possible with fresh price updates, as the user shortfall would not fall below 1 in the given scenario of volatile prices.
getPriceUnsafe()
. Utilize a fallback API3 oracle if freshness criteria are not met.sherlock-admin2
The protocol team fixed this issue in the following PRs/commits:
https://github.com/Mach-Finance/contracts/pull/8