Omniscia Euler Finance Audit

Governance Manual Review Findings

Governance Manual Review Findings

GOV-01M: Inexistent Sanitization of Pricing Type

Description:

The pricing type a particular e-asset conforms to is not validated in the setPricingConfig function, allowing yet unsupported types to be submitted. As an example, an asset may already have the PRICINGTYPE__CHAINLINK type on-chain and cause issues after the contract is upgraded to support it.

Impact:

An unsanitized pricing type can lead to an unusable pricing mechanism.

Example:

contracts/modules/Governance.sol
48function setPricingConfig(address underlying, uint16 newPricingType, uint32 newPricingParameter) external nonReentrant governorOnly {
49 address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
50 require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
51
52 AssetStorage storage assetStorage = eTokenLookup[eTokenAddr];
53 AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
54
55 assetStorage.pricingType = assetCache.pricingType = newPricingType;
56 assetStorage.pricingParameters = assetCache.pricingParameters = newPricingParameter;
57
58 if (newPricingType == PRICINGTYPE__CHAINLINK) {
59 require(chainlinkPriceFeedLookup[underlying] != address(0), "e/gov/chainlink-price-feed-not-initialized");
60 }
61
62 emit GovSetPricingConfig(underlying, newPricingType, newPricingParameter);
63}

Recommendation:

We advise the newPricingType variable to be properly sanitized as being within bounds of the permitted values showcased in the Constants.sol contract.

Alleviation:

A new PRICINGTYPE__OUT_OF_BOUNDS variable was introduced that is used to guarantee the newPricingType represents a supported and sensible pricing type thus resolving this exhibit.

Description:

The linked setChainlinkPriceFeed function adjusts the aggregator of a particular asset by manually specifying the Aggregator by the governor. This trait allows an Aggregator for an unrelated asset to be set for another as there is no guarantee of association between the oracle and the asset.

Impact:

A mismatched oracle will cause potentially significant price discrepancies between the underlying asset and its reported oracle price presenting arbitrage opportunities. Additionally, validating aggregator - asset pairs is impractical off-chain.

Example:

contracts/modules/Governance.sol
104function setChainlinkPriceFeed(address underlying, address chainlinkAggregator) external nonReentrant governorOnly {
105 address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
106 require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
107
108 chainlinkPriceFeedLookup[underlying] = chainlinkAggregator;
109
110 emit GovSetChainlinkPriceFeed(underlying, chainlinkAggregator);
111}

Recommendation:

We advise the Chainlink Feed Registry to be utilized and in particular their getFeed function which permits aggregators to be dynamically fetched for a particular base / quote pair. In order for the governance mechanism to function properly, we also advise the mapping that associates assets with aggregators to be adjusted to a mapping that associates assets with activated Chainlink oracles using the bool data type.

Alleviation:

We carefully evaluated this exhibit via discussions with the Euler Finance team and concluded that the significantly increased complexity of integrating with the Chainlink Feed Registry outweighs the potential security benefit acquired as the existing implementation will undergo rigorous vetting during the governance proposal's consideration. As a result, we will classify this exhibit as nullified due to the short-comings of a potential Chainlink Feed Registry integration.

GOV-03M: Inexistent Guarantee of Smooth Oracle Transition

Description:

The governance module of the system was adjusted to support overriding the oracle type of a particular asset with a new one without any safeguards in place guaranteeing that the reported discrepancy between the oracles is sane.

Impact:

As the pricing oracle replacement is instantaneous, arbitreurs can benefit from the price discrepancy between the previous and new oracle types using transaction ordering attacks such as MEV blocks.

Example:

contracts/modules/Governance.sol
48function setPricingConfig(address underlying, uint16 newPricingType, uint32 newPricingParameter) external nonReentrant governorOnly {
49 address eTokenAddr = underlyingLookup[underlying].eTokenAddress;
50 require(eTokenAddr != address(0), "e/gov/underlying-not-activated");
51
52 AssetStorage storage assetStorage = eTokenLookup[eTokenAddr];
53 AssetCache memory assetCache = loadAssetCache(underlying, assetStorage);
54
55 assetStorage.pricingType = assetCache.pricingType = newPricingType;
56 assetStorage.pricingParameters = assetCache.pricingParameters = newPricingParameter;
57
58 if (newPricingType == PRICINGTYPE__CHAINLINK) {
59 require(chainlinkPriceFeedLookup[underlying] != address(0), "e/gov/chainlink-price-feed-not-initialized");
60 }
61
62 emit GovSetPricingConfig(underlying, newPricingType, newPricingParameter);
63}

Recommendation:

We advise a delta threshold to be applied between current price readings of the previous and new oracle readings to ensure no arbitrage opportunity presents itself when an oracle adjustment transaction is submitted on-chain.

Alleviation:

After discussing with the Euler Finance team, we elaborated on the original exhibit's purpose and stated that the delta threshold enforced should not be prohibitive but rather pause certain components of the system after replacing the oracle which would then require manual intervention. The Euler Finance team proceeded to maintain that they do not believe that a delta threshold is sensible in the way they have structured the overall Euler system and as such will proceed with no change in this exhibit. As a result, we consider this exhibit acknowledged.