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;
}
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()
andousgInstantManager.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 callousgInstantManager.pauseMint()
andousgInstantManager.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.Assessed type
Oracle