Boost _ Folks Finance 33441 - [Smart Contract - Insight] Protocol uses Pyth to fetch price which is a pull based oracle and requires price updates to be pushed by the user which is not taken care off
Last updated
Was this helpful?
Last updated
Was this helpful?
Submitted on Sat Jul 20 2024 14:05:39 GMT-0400 (Atlantic Standard Time) by @Tripathi for
Report ID: #33441
Report type: Smart Contract
Report severity: Insight
Target: https://testnet.snowtrace.io/address/0xA758c321DF6Cd949A8E074B22362a4366DB1b725
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Protocol uses Pyth to fetch price which is a pull based oracle and requires price updates to be pushed by the user which is not taken care off. There used to be 2 kind of Oracles Pull based on push based.
Push based - https://docs.pyth.network/price-feeds/pull-updates#push-oracles
Pull based - https://docs.pyth.network/price-feeds/pull-updates#pull-oracles
NOTE - pyth doesn't push the prices updates onchain contracts ever it is user responsibility to update the price before using it
.
Since Pyth is pull based which requires price updates to be pushed by the user before calling PythNode::process()
to fetch balances.
Implementation of Pyth pull based oracle have 2 steps
Implement a onchain conract which integrates pyth onchain network this will enable protocol to accept pyth price, update messages and validate that they are authentic by doing sanity checks. This is done in current implementation
Users of the protocol need to update the price onchain before consuming it.
This can be done before calling PythNode::process()
dispatch a call updatePriceFeeds on the Pyth oracle proxy to refresh the price. Or provide a interface for users for updating price before consuming it.
Pyth Oracle doesn' update price on its own. User need to update the price before consuming it. Since folks finance fail to integrate Pyth correctly user will end of consuming stale price which is not up to date
https://www.youtube.com/watch?v=qdwrs23Qc9g this could help to understand the integration issues betterr
https://docs.pyth.network/price-feeds/pull-updates#pull-oracles
or Euler or any other protocol which already sets an example for best integration
Currently PythNode::process()
uses pyth.getPriceUnsafe()
and pyth.getEmaPriceUnsafe()
before updating the price, SO USer will consume the stale price which is not upto date.
Showing a POC on onchain condintions
Setting environment from original repo seems difficult so created onchain similar environment to show POC
Copy above contract and deploy in the remix.
Call ImplementedfetchPrice()
on any chain or testnet(also change corresponding priceFeedId ) and note the returned price
Now call CorrectFetchPrice()
by updating the price. For priceUpdate
calldata fetch this from Hermes. And note the price. https://docs.pyth.network/price-feeds/api-reference/evm/update-price-feeds this could help
At 1:30UTC eth/usd price went from 3498 to 3490 in some miliseconds. FOr me first call returned ~3494 and second call returned ~3490
The first method is going to return 3498 and correct method will return 3490 USDC. This is what i'm referring. Pull based oracle doesn't update this price updates while user are expected to fetch the price update from offchain Hermes
in this case and update the price before using it.
In this case
https://github.com/Folks-Finance/folks-finance-xchain-contracts/blob/main/contracts/hub/logic/LiquidationLogic.sol#L185
In such cases processPriceFeed will give inflated or stale values which will lead to loss of funds for user and protocol.
https://in.tradingview.com/symbols/ETHUSD/ whenever there is a sudden change call both function and check the difference.
ImplementedfetchPrice()
represents the which consume price from pyth.getEmaPriceUnsafe()
and pyth.getPriceUnsafe()
methods.
Check how manages dispatch a call updatePriceFeeds
on the Pyth oracle proxy to refresh the price before any consumption of price