Omniscia Euler Finance Audit

RethOracle Manual Review Findings

RethOracle Manual Review Findings

ROE-01M: Potentially Stale Calculation of Exchange Rate (Asynchronous Rewards / Penalties)

Description:

The rETH contract implementation exposes utility functions for calculating the on-chain conversion of the two assets rather than the exchange rate that is influenced by the "true" value of the asset. In practical terms, the IReth::getEthValue and IReth::getRethValue functions do not reflect future profits already captured that the Rocket Pool contracts will reflect via a manual update of the Rocket Pool's network balances.

Per the Rocket Pool documentation, the balances of the Rocket Pool system are updated at a 24-hour interval providing adequate time for a user to be knowledgeable of the shift in the exchange rate and to capitalize on it.

Impact:

The RethOracle::_getQuote function will consistently undervalue the rETH asset in relation to the ETH asset due to not accounting for earned but not yet reflected rewards of the Beacon Chain node operators that are affiliated with Rocket Pool. Additionally, the same function may overvalue the rETH asset in relation to the ETH asset if losses incurred by Rocket Pool have not yet been reflected on-chain.

Example:

src/adapter/rocketpool/RethOracle.sol
25/// @notice Get a quote by querying the exchange rate from the rETH contract.
26/// @dev Calls `getEthValue` for rETH/WETH and `getRethValue` for WETH/rETH.
27/// @param inAmount The amount of `base` to convert.
28/// @param base The token that is being priced. Either `rETH` or `WETH`.
29/// @param quote The token that is the unit of account. Either `WETH` or `rETH`.
30/// @return The converted amount.
31function _getQuote(uint256 inAmount, address base, address quote) internal view override returns (uint256) {
32 if (base == reth && quote == weth) {
33 return IReth(reth).getEthValue(inAmount);
34 } else if (base == weth && quote == reth) {
35 return IReth(reth).getRethValue(inAmount);
36 }
37 revert Errors.PriceOracle_NotSupported(base, quote);
38}

Recommendation:

The Rocketpool ecosystem contains a RocketNetworkBalances deployment that marks the last block that a balance update occurred. This value can be utilized to detect the time that has elapsed since the last balance update, and prevent an exchange rate from being considered as valid if the time exceeds 24 hours or a smaller duration.

Alternatively or as an additional measure, the code could query the TWAP exchange rate of an ETH-rETH AMM and enforce a deviation threshold between the two price measurements.

Alleviation:

The Euler Finance team evaluated this exhibit and, after a careful assessment and economical analysis of the operational security and accuracy of the exchange rate provided by the Rocketpool contracts, proceeded with removing the oracle implementation from the codebase altogether.

As such, we consider this exhibit indirectly alleviated as it prompted an economical analysis of the Rocketpool oracle that resulted in a tangible adjustment to the codebase.