Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: medium
Invalid

Missing Feed Data Verification in raiseAlert() Function

Summary

The raiseAlert() function in the OperatorVault contract does not verify the validity of the Chainlink price feed data before raising an alert. Specifically, it lacks checks for whether the feed data is stale or incorrect. This could result in the function raising false alerts based on outdated or incorrect data, potentially causing unnecessary gas consumption and operational issues.

Vulnerability Details

https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/linkStaking/OperatorVault.sol#L126

function raiseAlert(address _feed) external onlyOperator {
uint256 prevBalance = token.balanceOf(address(this));
pfAlertsController.raiseAlert(_feed);
uint256 rewards = token.balanceOf(address(this)) - prevBalance;
uint256 opRewards = (rewards * IOperatorVCS(vaultController).operatorRewardPercentage()) /
10000;
token.safeTransfer(vaultController, rewards - opRewards);
emit AlertRaised();
}

Stale Feed Data: The function raises an alert without verifying if the Chainlink feed's latest data is stale. In a live environment, if the feed has not been updated for a certain time (due to a network delay, issues with the oracle, etc.), the alert could be raised based on outdated information.

  • Incorrect Data Handling: The function does not check if the feed's current value deviates from an expected or acceptable range, meaning it could raise an alert unnecessarily even when no actual issue is present.

  • Impact

High, as it can result in the application working with an incorrect asset price

Tools Used

Manual review

Recommendations

Check for Stale Data: Add logic to check the timestamp of the last price feed update (using updatedAt) against the current block timestamp. If the feed hasn't been updated within a predefined threshold, then raise the alert.

  • Check for Value Deviations: Compare the feed's latest value with a reference or expected value to ensure it is within an acceptable range before raising an alert.

    function raiseAlert(address _feed) external onlyOperator {
    (
    uint80 roundID,
    int256 price,
    uint256 startedAt,
    uint256 updatedAt,
    uint80 answeredInRound
    ) = priceFeed.latestRoundData();
    // Check if feed value is stale
    if (block.timestamp - updatedAt > staleThreshold) {
    // Raise alert if feed is stale
    pfAlertsController.raiseAlert(_feed);
    uint256 prevBalance = token.balanceOf(address(this));
    uint256 rewards = token.balanceOf(address(this)) - prevBalance;
    uint256 opRewards = (rewards * IOperatorVCS(vaultController).operatorRewardPercentage()) / 10000;
    token.safeTransfer(vaultController, rewards - opRewards);
    emit AlertRaised();
    } else {
    revert("Feed is not stale, no alert raised.");
    }
    }
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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