QuantAMM

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

Unprotected Initialization Function in QuantAMMWeightedPool Enables Front-Running Attack Leading to Pool Takeover and Value Extraction

Summary

The initialize function in QuantAMMWeightedPool is only protected by the initializer modifier but lacks proper access control. While the initializer modifier ensures the function can only be called once, it does not restrict who can call it. This creates a critical vulnerability where an attacker could front-run the legitimate initialization transaction and initialize the contract with malicious parameters.

The impact of a successful front-running attack would create severe security implications. An attacker who successfully front-runs the initialization could gain control over critical pool parameters, particularly the ability to set malicious initial weights that could be exploited for manipulation. The attacker would also gain control over the oracleStalenessThreshold setting, which could be manipulated to allow stale or inaccurate price data to be accepted by the pool. Furthermore, the ability to register unauthorized or malicious assets in the pool would enable various forms of pool manipulation and potential value extraction.

Since the initializer modifier prevents subsequent initialization calls, the legitimate owner would be permanently locked out of initializing the contract with the intended parameters. This situation would necessitate a complete contract redeployment, resulting in significant operational disruption, gas costs, and potential financial losses for users who may have already started interacting with the compromised contract.

Proof of Concept

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/QuantAMMWeightedPool.sol#L694

function initialize(
int256[] memory _initialWeights,
PoolSettings memory _poolSettings,
int256[] memory _initialMovingAverages,
int256[] memory _initialIntermediateValues,
uint _oracleStalenessThreshold
) public initializer { // Only has initializer modifier, missing access control
// ... rest of initialization code
}

Recommended Mitigation Steps

  1. Add access control to the initialize function using the onlyOwner modifier:

function initialize(
int256[] memory _initialWeights,
PoolSettings memory _poolSettings,
int256[] memory _initialMovingAverages,
int256[] memory _initialIntermediateValues,
uint _oracleStalenessThreshold
) public initializer onlyOwner { // Add onlyOwner modifier
// ... rest of initialization code
}
  1. Alternatively, if using OpenZeppelin's Initializable, consider implementing a two-step initialization process where:

  • The constructor sets the initial owner

  • The initialize function can only be called by that owner

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas / Admin is trusted / Pool creation is trusted / User mistake / Suppositions

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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