Boost _ Folks Finance 33441 - [Smart Contract - Insight] Protocol uses Pyth to fetch price which is

Submitted on Sat Jul 20 2024 14:05:39 GMT-0400 (Atlantic Standard Time) by @Tripathi for Boost | Folks Finance

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

Description

Brief/Intro

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.

Vulnerability Details

Implementation of Pyth pull based oracle have 2 steps

  1. 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

  1. 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.

Impact Details

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

Reference

  1. https://www.youtube.com/watch?v=qdwrs23Qc9g this could help to understand the integration issues betterr

  2. https://docs.pyth.network/price-feeds/pull-updates#pull-oracles

or Euler or any other protocol which already sets an example for best integration

POC

  1. 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

Proof of concept

Proof of Concept

Setting environment from original repo seems difficult so created onchain similar environment to show POC

Copy above contract and deploy in the remix.

  1. ImplementedfetchPrice() represents the PythNode::process() which consume price from pyth.getEmaPriceUnsafe() and pyth.getPriceUnsafe() methods.

  2. Call ImplementedfetchPrice() on any chain or testnet(also change corresponding priceFeedId ) and note the returned price

  3. 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.

Check Euler how manages dispatch a call updatePriceFeeds on the Pyth oracle proxy to refresh the price before any consumption of price

Last updated

Was this helpful?