code-423n4 / 2024-03-ondo-finance-findings

5 stars 6 forks source link

Oracle `getOUSGPrice()` can return outdated price. #196

Closed c4-bot-6 closed 6 months ago

c4-bot-6 commented 6 months ago

Lines of code

https://github.com/code-423n4/2024-03-ondo-finance/blob/78779c30bebfd46e6f416b03066c55d587e8b30b/contracts/ousg/rOUSG.sol#L378-L380 https://github.com/code-423n4/2024-03-ondo-finance/blob/78779c30bebfd46e6f416b03066c55d587e8b30b/contracts/ousg/ousgInstantManager.sol#L479-L485

Vulnerability details

Summary

rOUSG.getOUSGPrice() and ousgInstantManager.getOUSGPrice() are used to get current data of OUSG in USDC. But these functions have no validation if oracle returns outdated data. If backend loses connection (network issues) or loses access to oracle contract, and it's not noticed in time to call ousgInstantManager.pauseMint() and ousgInstantManager.pauseRedeem() price can vary enough to make arbitrage even in an hour of stale (at least to cover fees which are not more then 0.02%).

Impact

If price is not updated long enough and price on exchanges satisfy diference of prices and commission of protocols, users can use this opportunity to make large arbitrage trades (minimum deposit 100_000e6 USDC, minimum redeem 50_000e6 USDC) and cause loss of funds to ousgInstantManager.sol.

Recommended Mitigation Steps

Checking whether data returned from oracle is outdated or not can prevent such scenario. IRWAOracle interface already returns timestamp when price was updated. It is necessary to check depending on the oracle update frequency. In this example 30 minutes.

@@ -476,12 +476,20 @@ contract OUSGInstantManager is
    *
    * @return price The current price of OUSG in USDC
    */
-  function getOUSGPrice() public view returns (uint256 price) {
-    (price, ) = oracle.getPriceData();
+  function getOUSGPrice() public view returns (uint256) {
+    (uint256 price, uint256 timestamp) = oracle.getPriceData();
+
+    require(
+      block.timestamp <= timestamp + 30 minutes,
+      "OUSGInstantManager::getOUSGPrice: Price is outdated"
+    );
+
     require(
       price > MINIMUM_OUSG_PRICE,
       "OUSGInstantManager::getOUSGPrice: Price unexpectedly low"
     );
+
+    return price;
   }

Assessed type

Oracle

c4-pre-sort commented 6 months ago

0xRobocop marked the issue as duplicate of #282

c4-pre-sort commented 6 months ago

0xRobocop marked the issue as duplicate of #144

c4-judge commented 6 months ago

3docSec marked the issue as unsatisfactory: Out of scope

c4-judge commented 6 months ago

3docSec marked the issue as unsatisfactory: Out of scope