QuantAMM

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

Wrong fees in UpliftOnlyExample due to stale price returned from getData()

Summary

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.

Vulnerability Details

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.

Impact

Loss of funds for the protocol due to incorrect fee calculations or financial harm to users for the same reason.

Tools Used

Manual review

Recommendations

If the primary oracle returns a stale price and no backup oracles are configured, the getData() function should revert.

Updates

Lead Judging Commences

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

Appeal created

ge6a Submitter
10 months ago
n0kto Lead Judge
9 months ago
n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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