Omniscia Euler Finance Audit
PythOracle Manual Review Findings
PythOracle Manual Review Findings
POE-01M: Inexistent Configurability of Confidence Width
Type | Severity | Location |
---|---|---|
Standard Conformity | PythOracle.sol:L15 |
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:
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
Type | Severity | Location |
---|---|---|
Standard Conformity | PythOracle.sol:L52 |
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:
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
Type | Severity | Location |
---|---|---|
Standard Conformity | PythOracle.sol:L44, L45 |
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:
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
Type | Severity | Location |
---|---|---|
Logical Fault | PythOracle.sol:L74 |
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:
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.