DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Invalid

Residual lack of sequencer uptime feed verifications

Summary

The lack of sequencer uptime verification was an issue that was reported in the previous Cyfrin audit.

Zaros has implemented the requirements to partially mitigate the issue however, it is not enforced meaning the issue can still occur.

Thus, we believe the current issue to not be considered a known issue as it deviates slightly from the previous.

Vulnerability Details

The sequencer is involved in different sections of the protocol where Chainlink oracles are used, notably in the MarginCollateralConfiguration::getPrice() function that is used to retrieve the USD price of a collateral which plays a vital role in a PnL based protocol.

https://github.com/Cyfrin/2024-07-zaros/blob/main/src/perpetuals/leaves/MarginCollateralConfiguration.sol#L68-L82

function getPrice(Data storage self) internal view returns (UD60x18 price) {
address priceFeed = self.priceFeed;
uint32 priceFeedHearbeatSeconds = self.priceFeedHearbeatSeconds;
GlobalConfiguration.Data storage globalConfiguration = GlobalConfiguration.load();
address sequencerUptimeFeed = globalConfiguration.sequencerUptimeFeedByChainId[block.chainid];
if (priceFeed == address(0)) {
revert Errors.CollateralPriceFeedNotDefined();
}
price = ChainlinkUtil.getPrice(
IAggregatorV3(priceFeed), priceFeedHearbeatSeconds, IAggregatorV3(sequencerUptimeFeed)
);
}

First, this function DOES verify that the priceFeed is set BUT DOESN'T verify the sequencerUptimeFeed is.

If we take a look at the ChainlinkUtil.getPrice() function, we notice it performs a verification regarding the sequencerUptimeFeed but still allows the transaction to proceed in case it has not been set.

https://github.com/Cyfrin/2024-07-zaros/blob/main/src/external/chainlink/ChainlinkUtil.sol#L41-L57

if (address(sequencerUptimeFeed) != address(0)) {
try sequencerUptimeFeed.latestRoundData() returns (
uint80, int256 answer, uint256 startedAt, uint256, uint80
) {
bool isSequencerUp = answer == 0;
if (!isSequencerUp) {
revert Errors.OracleSequencerUptimeFeedIsDown(address(sequencerUptimeFeed));
}
uint256 timeSinceUp = block.timestamp - startedAt;
if (timeSinceUp <= Constants.SEQUENCER_GRACE_PERIOD_TIME) {
revert Errors.GracePeriodNotOver();
}
} catch {
revert Errors.InvalidSequencerUptimeFeedReturn();
}
}
try priceFeed.latestRoundData() returns (uint80, int256 answer, uint256, uint256 updatedAt, uint80) {
// ......

The sequencer address is set through the GlobalConfigurationBranch::configureSequencerUptimeFeedByChainId() function meaning the system can be deployed successfully without the sequencer uptime feed being set.

Impact

All the prices retrieved from the Chainlink oracle can be stale in case the Arbitrum sequencer is down which could cause multiple issues in Zaros such as unexpected liquidations and risk free trades.

Tools Used

Manual review

Recommendations

In src/external/chainlink/ChainlinkUtil.sol make sure to revert the transaction in case the sequencer uptime feed is not set

Updates

Lead Judging Commences

inallhonesty Lead Judge
over 1 year ago
inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

`sequencerUptimeFeed` has not yet been configured

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!