<!-- canonical: https://0xsimao.com/findings/evro-finance-ii-sdai-price-feed-constructor -->

# SDAIPriceFeed missing constructor price feed check

Low/Info · Sherlock · EUR stablecoin · 26th December 2025

Finding L-1 of the Evro Collateral Onboarding security review.

- Report: /reports/evro-collateral-onboarding
- Source: https://github.com/0xsimao/audits/blob/main/Sherlock/private-audits/2025-12-26-evro-finance-ii.pdf

---

## Summary
The `SDAIPriceFeed` constructor does not call `_fetchPricePrimary()` to initialize `lastGoodPrice`, leaving it at zero and causing potential issues on first oracle failure.

## Vulnerability Detail
Unlike other price feeds (GNOPriceFeed, WBTCPriceFeed, etc.), `SDAIPriceFeed` does not call `_fetchPricePrimary()` in its constructor. This means:
1. `lastGoodPrice` starts at 0
2. If the first `fetchPrice()` call encounters an oracle failure, `_shutDownAndSwitchToLastGoodPrice()` returns 0
3. A price of 0 could cause division by zero or allow infinite borrowing

## Impact
If oracles fail on the first price fetch after deployment, the system returns a price of 0.

## Code Snippet
https://github.com/sherlock-audit/2025-12-evro-finance-dec-26th/blob/main/evro/contracts/src/PriceFeeds/SDAIPriceFeed.sol#L13-L21

```solidity
constructor(address _daiUsdOracleAddress, address _eurUsdOracleAddress, uint256 _daiUsdStalenessThreshold, uint256 _usdEurStalenessThreshold, address _borrowerOperationsAddress, address _sdaiAddress)
    MainnetPriceFeedBase(_daiUsdOracleAddress, _daiUsdStalenessThreshold, _borrowerOperationsAddress)
{
    eurUsdOracle.aggregator = AggregatorV3Interface(_eurUsdOracleAddress);
    eurUsdOracle.stalenessThreshold = _usdEurStalenessThreshold;
    eurUsdOracle.decimals = eurUsdOracle.aggregator.decimals();

    sdai = IERC4626(_sdaiAddress);

    // @audit - missing: _fetchPricePrimary();
    // @audit - missing: assert(priceSource == PriceSource.primary);
}
```

Compare to GNOPriceFeed:
https://github.com/sherlock-audit/2025-12-evro-finance-dec-26th/blob/main/evro/contracts/src/PriceFeeds/GNOPriceFeed.sol#L17-L18

```solidity
_fetchPricePrimary();
assert(priceSource == PriceSource.primary);
```

## Tool Used
Manual Review

## Recommendation
Add initialization in the constructor:

```solidity
constructor(...) MainnetPriceFeedBase(...) {
    eurUsdOracle.aggregator = AggregatorV3Interface(_eurUsdOracleAddress);
    eurUsdOracle.stalenessThreshold = _usdEurStalenessThreshold;
    eurUsdOracle.decimals = eurUsdOracle.aggregator.decimals();

    sdai = IERC4626(_sdaiAddress);

    _fetchPricePrimary();
    assert(priceSource == PriceSource.primary);
}
```

Disclosed by 0xSimao (https://0xsimao.com/).

---

Related findings:

- [Attacker can trigger temporary shutdown due to RedStonePriceFeedBase missing gas check](https://0xsimao.com/findings/felix-temporary-shutdown-price-gas): Felix Price Feeds
- [Missing priceFeedDisabled event in RedStonePriceFeedBase](https://0xsimao.com/findings/felix-price-disabled-red-stone): Felix Price Feeds
- [PriceFeed: First owner isn't set as valid keeper](https://0xsimao.com/findings/nftperp-i-price-isn-valid-keeper): Nftperp Exchange
- [PriceFeed: Two step owner transfers are safer](https://0xsimao.com/findings/nftperp-i-price-two-transfers-safer): Nftperp Exchange
