QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

QuantAMM Oracle Operates Without L2 Sequencer Status Check, Enabling Stale Price Trading During Downtime

Description

The ChainlinkOracle contract critically undermines QuantAMM's TFMM mechanism by lacking L2 sequencer status validation. When deployed on Layer 2 networks, the _getData() function blindly retrieves price data without verifying sequencer operational status, creating a severe vulnerability in the protocol's automated portfolio management system.

QuantAMM's continuous rebalancing architecture becomes particularly vulnerable during sequencer downtime or delays. The TFMM mechanism continues executing weight adjustments based on potentially stale oracle data, while the sequencer's unavailability prevents any corrective market actions. This creates a dangerous asymmetry where portfolio rebalancing continues operating on outdated information, potentially mismanaging significant assets under the protocol's control.

In QuantAMM's composite pool structure, this vulnerability becomes systemic. When the sequencer is down, the temporal function calculations continue processing with stale data, causing incorrect weight adjustments across multiple linked strategies. BTF operations become especially risky as unit values and portfolio allocations may significantly diverge from actual market conditions. Upon sequencer recovery, the backlog of automated strategy adjustments could execute with outdated parameters, causing severe portfolio imbalances.

Proof of Concept

https://github.com/Cyfrin/2024-12-quantamm/blob/main/pkg/pool-quantamm/contracts/ChainlinkOracle.sol#L27

function _getData() internal view override returns (int216, uint40) {
(, /*uint80 roundID*/ int data, , /*uint startedAt*/ uint timestamp, ) = /*uint80 answeredInRound*/
priceFeed.latestRoundData();
require(data > 0, "INVLDDATA");
data = data * int(10 ** normalizationFactor);
return (int216(data), uint40(timestamp));
}

Recommended mitigation steps

Implement L2 sequencer status verification:

contract ChainlinkOracle is OracleWrapper {
AggregatorV3Interface public immutable sequencerFeed;
uint256 public constant GRACE_PERIOD = 3600; // 1 hour
constructor(
address _chainlinkFeed,
address _sequencerFeed
) {
require(_sequencerFeed != address(0), "INVALID_SEQUENCER");
sequencerFeed = AggregatorV3Interface(_sequencerFeed);
}
function _checkSequencer() internal view {
(, int256 status, , uint256 lastUpdateTime, ) = sequencerFeed.latestRoundData();
// Check sequencer status
bool isSequencerUp = status == 0;
bool isUpdated = block.timestamp - lastUpdateTime < GRACE_PERIOD;
if (!isSequencerUp || !isUpdated) {
revert SequencerDown(status, lastUpdateTime);
}
}
function _getData() internal view override returns (int216, uint40) {
// Verify sequencer status first
_checkSequencer();
(, int256 data, , uint256 updatedAt, ) = priceFeed.latestRoundData();
require(data > 0, "INVLDDATA");
data = data * int(10 ** normalizationFactor);
return (int216(data), uint40(updatedAt));
}
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

invalid_sequencer_status_chainlink_and_L2

LightChaser: ## [Medium-6] Missing checks for whether the L2 Sequencer is active ## [Low-22] Chainlink sequencer status is not checked

Support

FAQs

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