Omniscia Euler Finance Audit
RethOracle Manual Review Findings
RethOracle Manual Review Findings
ROE-01M: Potentially Stale Calculation of Exchange Rate (Asynchronous Rewards / Penalties)
Type | Severity | Location |
---|---|---|
External Call Validation | RethOracle.sol:L33, L35 |
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:
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.