Omniscia Euler Finance Audit
PythOracle Code Style Findings
PythOracle Code Style Findings
POE-01C: Potentially Redundant Function Implementation
Type | Severity | Location |
---|---|---|
Standard Conformity | PythOracle.sol:L48-L53 |
Description:
In contrast to the RedstoneCoreOracle::updatePrice
function that records local data points, the PythOracle::updatePrice
function will simply forward a call to a permissionless function of the IPyth
implementation.
Impact:
As the PythOracle::updatePrice
function does not expose any novel statements and simply forwards a call with no additional logic, its presence is unnecessary and integrators should make sure the oracles are updated whenever necessary.
Example:
48/// @notice Update the price of the Pyth feed.49/// @param updateData Price update data. Must be fetched off-chain.50/// @dev The required fee can be computed by calling `getUpdateFee` on Pyth with the length of the `updateData` array.51function updatePrice(bytes[] calldata updateData) external payable {52 IPyth(pyth).updatePriceFeeds{value: msg.value}(updateData);53}
Recommendation:
We advise the function to be removed altogether, ensuring the caller is responsible for updating the IPyth
oracle data points if necessary.
Alleviation:
The relevant function has been properly removed from the PythOracle
implementation, and the Euler Finance team has clarified that callers are expected to update the Pyth oracle price via a batch EVK call directly.
POE-02C: Redundant Handling of Positive Exponent
Type | Severity | Location |
---|---|---|
Gas Optimization | PythOracle.sol:L66 |
Description:
Per the Pyth Network Solidity SDK validation as well as what a positive exponent would infer, the Pyth Network is expected to report solely non-positive exponent values during its operation. As a result, custom handling of a potentially positive exponent in the ScaleUtils
implementation is unnecessary.
Example:
55/// @notice Fetch the latest Pyth price and transform it to a quote.56/// @param inAmount The amount of `base` to convert.57/// @param _base The token that is being priced.58/// @param _quote The token that is the unit of account.59/// @return The converted amount.60function _getQuote(uint256 inAmount, address _base, address _quote) internal view override returns (uint256) {61 bool inverse = ScaleUtils.getDirectionOrRevert(_base, base, _quote, quote);62
63 PythStructs.Price memory priceStruct = _fetchPriceStruct();64 uint256 price = uint256(uint64(priceStruct.price));65
66 Scale scale = ScaleUtils.calcScale(baseDecimals, quoteDecimals, int8(priceStruct.expo));67 return ScaleUtils.calcOutAmount(inAmount, price, scale, inverse);68}69
70/// @notice Get the latest Pyth price and perform sanity checks.71/// @dev Reverts if price is non-positive, confidence is too wide, or exponent is too large.72function _fetchPriceStruct() internal view returns (PythStructs.Price memory) {73 PythStructs.Price memory p = IPyth(pyth).getPriceNoOlderThan(feedId, maxStaleness);74 if (p.price <= 0 || p.conf > uint64(p.price) * MAX_CONF_WIDTH / 10_000 || p.expo > 16 || p.expo < -16) {75 revert Errors.PriceOracle_InvalidAnswer();76 }77 return p;78}
Recommendation:
We advise the priceStruct.expo
to be cast to a uint8
after being negated, optimizing the bytecode size of the contracts whilst reducing their complexity.
Alleviation:
Alongside remediations carried out for POE-04M
, the referenced statement was optimized to invoke ScaleUtils::from
directly thus addressing this exhibit.