The QuantAMMWeightedPool
contract allows dynamic weight adjustments through a blockMultiplier
mechanism. However, there is no upper bound validation for the blockMultiplier
, enabling excessive values to be set. This leads to rapid inflation of token weights within the pool, causing significant imbalance and exposing liquidity providers (LPs) to arbitrage losses. The issue persists in the setWeights
function, where no limit restricts the multiplier values.
Note: Do not confuse this vulnerability with the one previously reported by Cyfrin titled “Incorrect handling of negative multipliers.” While both findings relate to the handling of blockMultiplier
and its effects on weight calculations, Cyfrin's report focuses on errors caused by negative values (leading to underflow), whereas this new vulnerability targets excessive multipliers (e.g., > 1) that destabilize the pool.
The QuantAMMWeightedPool
contract relies on a blockMultiplier
to interpolate token weights over time. However, the implementation does not enforce an upper bound on the blockMultiplier
. As a result, when a malicious or flawed external rule sets a multiplier to an excessively high value (e.g., 2e18 or beyond), the token’s weight inflates rapidly in just a few blocks or seconds. This leads to the following issues:
Extreme Weight Imbalances: One token’s weight can quickly exceed 1e18
(100%), causing other tokens to lose nearly all of their share in the pool.
Price Manipulation: Swaps become mispriced because the pool’s formula believes one token dominates the entire pool, allowing arbitrageurs to exploit the discrepancy.
Significant LP Losses: Liquidity providers face amplified slippage and potential impermanent losses, as the pool’s mispriced ratio encourages large profit-taking swaps by external actors.
By allowing an unlimited blockMultiplier
, the pool fails to prevent scenarios where a single token effectively “absorbs” the entire pool in a short timeframe, revealing a high-severity vulnerability that directly impacts pool stability and user funds.
The root cause is the lack of validation in the setWeights
function for blockMultiplier
values. The function accepts arrays of weights and multipliers but does not enforce an upper bound on the multiplier values, allowing arbitrary inflation.
QuantAMMWeightedPool.sol - setWeights
The vulnerability is in the setWeights
function:
An excessive blockMultiplier
immediately threatens the pool’s stability. When weights inflate beyond 1.0 for a single token, the pool’s pricing logic breaks, making that token appear to dominate the entire liquidity. This leads to:
Severe Arbitrage Opportunities: External actors see a token over-represented and swap in or out at highly favorable rates, causing sudden and large losses to the pool’s liquidity providers (LPs).
Rapid Liquidity Drain: Other tokens effectively lose their share of the pool, creating price imbalances that incentivize large‐scale swaps against the inflated token.
Unchecked Price Manipulation: The AMM formula relies on normalized weights. If a weight becomes greater than 1.0, the implied pricing model no longer reflects reality, leaving the pool vulnerable to exploit.
Because this happens without triggering any safe‐stop mechanism, the potential for immediate, irreversible loss is high, making it a critical issue for all users of the pool.
Add the following test to pkg/pool-quantamm/test/foundry/QuantAMMWeightedPool2Token.t.sol
:
Explanation
The base weight starts at 0.5e18
for token0 and token1.
A blockMultiplier
of 2e18
for token0 quickly inflates its effective weight.
After interpolating for just 5 seconds, the total combined weights exceed 1e18
.
Add the following test to pkg/pool-quantamm/test/foundry/QuantAMMWeightedPool2Token.t.sol
:
Additional Research
The fuzz test explores multiple random multipliers ≥ 1e18
, consistently reproducing the vulnerability whenever blockMultiplier >= 1e18
.
Foundry: Executes unit tests and fuzz tests to illustrate that the pool does not revert on excessive multipliers.
Manual Code Review: To identify and confirm the absence of multiplier validation in the setWeights
function.
Enforce an Upper Bound on Multiplier
In setWeights(...)
, add a check that reverts if any blockMultiplier
≥ 1e18 (or a suitably safe threshold). Example:
Optionally Limit Summations
If desired, ensure that at no interpolation point can a token’s weight exceed 1.0 individually, or that the sum never surpasses 1.0 across the whole pool.
Audit External Weight Update Rules
Verify that off-chain or separate “weight update” logic does not produce large multipliers beyond the allowed threshold.
After adding the recommended mitigation to the QuantAMMWeightedPool
contract, include the following test in pkg/pool-quantamm/test/foundry/QuantAMMWeightedPool2Token.t.sol
:
This mitigation ensures that excessively large multipliers are rejected, preventing pool imbalances and protecting LPs.
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.