Omniscia Euler Finance Audit

PythOracle Manual Review Findings

PythOracle Manual Review Findings

POE-01M: Inexistent Configurability of Confidence Width

Description:

The MAX_CONF_WIDTH variable within the PythOracle is not configurable despite the oracle being meant to be compatible with multiple asset classes.

Impact:

A ±5% confidence interval for stablecoins is considered a significant deviation in contrast to high-volatility assets such as cryptocurrencies.

Example:

src/adapter/pyth/PythOracle.sol
14/// @dev The confidence interval can be at most (-5%,+5%) wide.
15uint256 internal constant MAX_CONF_WIDTH = 500;

Recommendation:

We advise the variable to be up to the deployer's discretion as stablecoins and other relatively stable assets would require a narrower confidence interval to avoid manipulation.

Alleviation:

The MAX_CONF_WIDTH constant has been removed from the contract in favour of the newly introduced maxConfWidth variable that is immutable and configured during the contract's deployment.

POE-02M: Inexistent Prevention of Overpayment

Description:

The PythOracle::updatePrice function permits the caller to overpay the IPyth oracle which we consider incorrect.

Impact:

A caller is permitted to overpay for a price update and the IPyth oracle will not perform any refund of surplus funds. While it is the responsibility of the caller to ensure sufficient native funds have been provided, the update fee may change between a transaction's submission and a transaction's execution in the network and as such dynamic evaluation of the necessary funds is a better approach.

Example:

src/adapter/pyth/PythOracle.sol
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 code to calculate the update fee via the IPyth::getUpdateFee function, and to forward the exact amount of native funds necessary.

The code can either mandate the exact amount of native funds necessary have been transmitted, or to refund any remainder to the caller, either of which we consider a valid alleviation.

Alleviation:

The exhibit has been rendered inapplicable due to the removal of the relevant function as part of efforts addressing POE-01C.

POE-03M: Potentially Unsupported Function Signature

Description:

The code of the PythOracle::constructor will invoke the IERC20::decimals function as exposed by the forge-std library, however, the IERC20::decimals function is not actually part of the EIP-20 specification.

Impact:

Most EIP-20 assets do implement the IERC20::decimals function signature, however, it is not mandated by the standard and as such a small subset of EIP-20 tokens is incompatible with the PythOracle presently.

Example:

src/adapter/pyth/PythOracle.sol
32/// @notice Deploy a PythOracle.
33/// @param _pyth The address of the Pyth oracle proxy.
34/// @param _base The address of the base asset corresponding to the feed.
35/// @param _quote The address of the quote asset corresponding to the feed.
36/// @param _feedId The id of the feed in the Pyth network.
37/// @param _maxStaleness The maximum allowed age of the price.
38constructor(address _pyth, address _base, address _quote, bytes32 _feedId, uint256 _maxStaleness) {
39 pyth = _pyth;
40 base = _base;
41 quote = _quote;
42 feedId = _feedId;
43 maxStaleness = _maxStaleness;
44 baseDecimals = IERC20(_base).decimals();
45 quoteDecimals = IERC20(_quote).decimals();
46}

Recommendation:

In case all EIP-20 assets are expected to be supported, we advise decimals to either be opportunistically queried or for decimals to be supplied as input arguments thus permitting any token to have a PythOracle deployed.

Alleviation:

A common BaseAdapter::_getDecimals implementation has been introduced in the BaseAdapter upstream contract that will attempt to fetch the IERC20::decimals of an asset and default to 32 if they cannot be fetched.

As such, we consider this exhibit fully alleviated.

POE-04M: Improper Validation of Exponent

Description:

The exponent of the Pyth Network system is guaranteed to be negative as it is meant to increase the accuracy of the reported value. A positive exponent would result in a reduction of the reported price and thus a loss of accuracy which would not be normal.

The aforementioned assumption is also upheld by the Pyth Network's own Solidity SDK which considers an exponent above 0 to be invalid.

Impact:

A positive exponent should be considered an invalid measurement as it would result in the data point being expanded and thus being inaccurate due to truncated values.

Example:

src/adapter/pyth/PythOracle.sol
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 code to ensure that the exponent is negative, and to potentially permit more decimals than 16 in the negative range.

Additionally, we advise the price to be validated as strictly positive given that a price of 0 should be considered invalid as well per the Pyth Network SDK.

Alleviation:

The Euler Finance team introduced exponent validation that prevents it from being positive as well as below the value of -20, rendering this exhibit alleviated.

For transparency, the Euler Finance team reached out to the Pyth Network team for clarification in relation to the permitted exponent values and concluded that positive exponents are ultimately meant to be supported even if the official SDK implies otherwise.

To this end, the changes introduced for this exhibit have been reverted in the latest implementation of the Euler Finance codebase and the exhibit's recommendations should not be followed by other projects.