QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: medium
Valid

Wrong uplift fee calculation due to rounding down to 0

Summary

In the UpliftOnlyExample contract, the onAfterRemoveLiquidity() function serves as a hook called by the Vault during liquidity removal to enable the implementation of custom logic for a specific pool. In this case, it handles the uplift logic. A key aspect of this logic is determining whether the pool's value has changed in the period between the liquidity addition and its removal. The problem is that this calculation is not implemented correctly, which compromises the entire logic and leads to a loss of funds due to fees.

Vulnerability Details

localData.lpTokenDepositValueChange =
(int256(localData.lpTokenDepositValueNow) - int256(localData.lpTokenDepositValue)) /
int256(localData.lpTokenDepositValue); // <@audit
uint256 feePerLP;
// if the pool has increased in value since the deposit, the fee is calculated based on the deposit value
if (localData.lpTokenDepositValueChange > 0) { // <@audit
feePerLP =
(uint256(localData.lpTokenDepositValueChange) * (uint256(feeDataArray[i].upliftFeeBps) * 1e18)) /
10000;
}
// if the pool has decreased in value since the deposit, the fee is calculated based on the base value - see wp
else {
//in most cases this should be a normal swap fee amount.
//there always myst be at least the swap fee amount to avoid deposit/withdraw attack surgace.
feePerLP = (uint256(minWithdrawalFeeBps) * 1e18) / 10000;
}

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L474-L476

From the code, it can be seen that the new value is subtracted by the old value, and the result is divided by the old value to determine the percentage change. The problem is that the numerator is not multiplied by 1e18 beforehand, which leads to rounding down to 0 in cases where the numerator is smaller than the denominator. For example, if the old value is 10e18 and the value increases by 20%, the new value would be 12e18. In this case, (12e18 - 10e18) / 10e18 = 0 in Solidity. The smallest increase that would result in a non-zero value is a 2x increase.

Impact

Wrong fee calculation and loss of funds from fees.

Tools Used

Manual review

Recommendations

Multiply the numerator by 1e18 to fix the rounding down to 0.

Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding_onAfterRemoveLiquidity_lpTokenDepositValueChange_rounding_error_100%_minimum

Likelihood: High, every call to the function (withdraw) Impact: Low/Medium, uplift fees will be applied only when the price of one asset is doubled but fixed fees will still be collected.

Support

FAQs

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