The UpdateWeightRunner.getData() function is used to fetch prices for the respective tokens participating in the pool from the designated oracles. There is a primary oracle and backup oracles. This function is used both by the price update functionality and by the UpliftOnlyExample.getPoolLPTokenValue() function, which determines the value of the LP token when calculating fees for uplift. It turns out that the getData() function does not work correctly in some situations, leading to issues in UpliftOnlyExample.
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-quantamm/contracts/UpdateWeightRunner.sol#L347-L391
The problem is that the getData() function may return a stale price if the primary feed provides stale data and no backup oracles are configured. This issue was identified as M-04 in the audit report by Cyfrin. In that report, the issue was reviewed in the context of weight calculation logic and was acknowledged by the sponsors, who decided not to fix it because it was not considered a serious problem. I agree that, within the scope of Cyfrin's audit, this assessment is valid. However, the UpliftOnlyExample contract was not included in that audit.
In the context of UpliftOnlyExample, this issue becomes critical, leading to a loss of funds for both the protocol and liquidity providers (LPs). Therefore, I do not consider this a known issue.
The issue arises because getData() is used by getPoolLPTokenValue() to determine the LP token price, which is used during liquidity removal to calculate the uplift fee. In short, if the pool's price has increased, a higher fee is charged. However, if a stale price is returned, the pool's value will be incorrect, resulting in incorrect fee calculations. For example, a user could pay a higher fee if the stale price is higher than the actual price at that moment, or pay a lower fee if it is lower than the real price, which would harm the protocol.
Another scenario is that a user who notices that the stale price is higher than the actual price could add liquidity, saving fees when they later withdraw funds, because the lpTokenDepositValue in the poolsFeeData record would be higher than the real value.
Loss of funds for the protocol due to incorrect fee calculations or financial harm to users for the same reason.
Manual review
If the primary oracle returns a stale price and no backup oracles are configured, the getData() function should revert.
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.