DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: medium
Valid

Hardcoded Arbitrum Sequencer Check Causes Complete Denial of Service on Avalanche Network Deployment

Code Areas

Summary

The KeeperProxy contract implements a sequencer uptime verification that is specific to Arbitrum's L2 network. When deployed on Avalanche, this verification will always fail as it attempts to call an invalid sequencer address, resulting in a complete denial of service for critical keeper functions.

Vulnerability Details

According to the contest brief, this protocol is intended for Arbitrum or Avalanche, but the KeeperProxy contract includes an Arbitrum specific sequencer status check in its _validatePrice function, which is called before executing any keeper actions. This check uses a hardcoded Arbitrum sequencer uptime feed address:

sequencerUptimeFeed = AggregatorV2V3Interface(0xFdB631F5EE196F0ed6FAa767959853A9F217697D);

The contract then attempts to verify the sequencer status:

(
/*uint80 roundID*/,
int256 answer,
uint256 startedAt,
/*uint256 updatedAt*/,
/*uint80 answeredInRound*/
) = AggregatorV2V3Interface(sequencerUptimeFeed).latestRoundData();
bool isSequencerUp = answer == 0;
require(isSequencerUp, "sequencer is down");

While this check is necessary for Arbitrum's L2 network to ensure the sequencer is operational, it becomes problematic when the contract is deployed on Avalanche:

  1. The hardcoded address has no meaning on Avalanche

  2. Calls to this random address will revert

  3. This check is mandatory and runs before any keeper action

Impact Details

  • Complete denial of service for all keeper functions on Avalanche

  • Users' deposits become locked in the PerpetualVault contract

  • No orders can be executed

  • Protocol becomes non-functional on Avalanche network

Recommendations

  1. Make the sequencer check network-aware:

contract KeeperProxy {
bool public isArbitrum;
function initialize(bool _isArbitrum, address _sequencerFeed) external initializer {
__Ownable2Step_init();
isArbitrum = _isArbitrum;
if (_isArbitrum) {
require(_sequencerFeed != address(0), "invalid sequencer feed");
sequencerUptimeFeed = AggregatorV2V3Interface(_sequencerFeed);
}
}
function _validatePrice(address perpVault, MarketPrices memory prices) internal view {
if (isArbitrum) {
// Perform sequencer checks only on Arbitrum
(,int256 answer, uint256 startedAt,,) = sequencerUptimeFeed.latestRoundData();
require(answer == 0, "sequencer is down");
require(block.timestamp - startedAt > GRACE_PERIOD_TIME, "Grace period not over");
}
// Continue with other price validations...
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_Avalanche_has_no_sequencer

Likelihood: High, run and runNextAction will revert. Impact: Low, any deposit will be retrieve thanks to cancelFlow.

Support

FAQs

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