A race condition vulnerability exists in the QuantAMMWeightedPool contract where weight calculations can be manipulated during weight updates due to non-atomic loading of timing variables. This vulnerability could allow attackers to profit from inconsistent weight calculations through sandwich attacks.
The heart of the vulnerability lies in how the computeBalance function handles timing variables for weight calculations. Instead of loading timing variables atomically (in a single storage read), it performs two separate storage reads which can become inconsistent during weight updates:
This implementation contrasts sharply with the more secure approach used in the onSwap function, which loads timing variables atomically:
The vulnerability can be exploited through a sophisticated sandwich attack that takes advantage of the timing inconsistency. Here's a detailed breakdown of the attack process:
Preparation Phase
Attacker monitors the mempool for weight update transactions
They analyze the current pool state and calculate optimal attack parameters
Prepare front-running and back-running transactions
Attack Execution
Front-running (Pre-update):
Deploy transaction with higher gas price than weight update
Execute swap using old, known weights
Transaction must complete before weight update
Weight Update Occurs:
Pool contract updates weights and timing variables
Creates vulnerable window for exploitation
Back-running (Exploitation):
Execute second transaction immediately after weight update
Exploit calculation discrepancy during vulnerable window
Profit from temporary mispricing
Lets try this with an example:
Initial Pool Configuration:
Front-run Transaction (T1):
Weight Update Occurs (T2):
Back-run Transaction (T3) - Exploiting Calculation Error:
Net Attack Results:
Direct profit opportunity for attackers
Proportional loss for liquidity providers
Scales with pool size and liquidity
Affects core pool mechanics
Compromises weight adjustment mechanism
Creates systemic instability in pool operations
Mitigation for this weight calculation race condition is to modify the computeBalance function to load all timing variables atomically using a single struct read, mirroring the safer implementation found in the onSwap function.
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.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.