The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

M-4 Price feed oracle data validation missing. Arb sequencer health check needed

Summary

The protocol relies on Chainlink price oracle, however it lacks checks for the staleness. Also Chainlink recommends that all Optimistic L2 oracles consult the Sequencer Uptime Feed to ensure that the sequencer is live before trusting the data returned by the oracle.

Vulnerability Details

Example:

  • A user has staked assets in LiqudationPool. Let’s say 100 EUROs, at rate eurUsd - $1.00 each (for simplicity)

  • The Arbitrum sequencer goes down temporarily

  • While it’s down the price of the usd falls to $0.50

  • User now has EUROs valued at $50

  • Because of the stale price the protocol will lead to incorrect calculations of costInEuros, then of _portion and it will distribute incorrect amount of assets to the user
    https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L220
    https://github.com/Cyfrin/2023-12-the-standard/blob/main/contracts/LiquidationPool.sol#L223

When the sequencer is live priceEurUsd = 100000000
When the sequencer is down priceEurUsd = 50000000
uint256 costInEuros = _portion * 10 ** (18 - asset.token.dec) * uint256(assetPriceUsd) / uint256(priceEurUsd)

Impact

If the Arbitrum sequencer goes down, the protocol will allow users to continue to operate at the previous (stale) rates and LiquidationPool.distributeAssets() will operate incorrectly. As it’s very rare case, but not impossible I consider it as a Medium,

Tools Used

Manual review

Recommendations

it is recommended to implement checks to ensure that the price returned by Chainlink is not stale. Please refer here for details https://docs.chain.link/data-feeds/l2-sequencer-feeds#example-code

...
( roundId, rawPrice, , updateTime, answeredInRound ) = AggregatorV3Interface(XXXXX).latestRoundData();
require(rawPrice > 0, "Chainlink price <= 0");
require(updateTime != 0, "Incomplete round");
require(answeredInRound >= roundId, "Stale price");
...
Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Arbitrum-sequncer

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

Arbitrum-sequncer

Support

FAQs

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