QuantAMM

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

Shared State Between Swap Fee and Uplift Fee Leads to Logic Vulnerability

Summary

The functions setQuantAMMSwapFeeTake and setQuantAMMUpliftFeeTake both update the same state variable, quantAMMSwapFeeTake. This causes the UpliftFee and SwapFee to always have identical values, even though the naming of the functions implies they are meant to be independent.

This creates a logic vulnerability where the intended separation of fees is violated, leading to potential confusion and unintended side effects in contract behavior.

Severity: Medium

Justification:
This vulnerability is classified as medium severity because:

  • There is no direct loss of funds or immediate security risk.

  • It breaks the intended business logic and fee management system.

  • It could lead to incorrect fee applications and financial discrepancies.

  • It affects administrative control but does not compromise the core protocol security.


Vulnerability Details

The vulnerability arises due to both setQuantAMMSwapFeeTake and setQuantAMMUpliftFeeTake modifying the same state variable, quantAMMSwapFeeTake. As a result, setting one fee inadvertently overwrites the value of the other, even though they are intended to represent distinct parameters.

This behavior is demonstrated in the test case below, where setting the SwapFee also changes the UpliftFee.

Affected code:
UpdateWeightRunner.sol#L126-L153

POC

Paste the following code into the UpdateWeightRunner.t.sol file:

function testSwapFeeSetsUpliftFee(uint256 fee) public {
uint256 boundFee = bound(fee, 0, 1e18);
vm.startPrank(owner);
updateWeightRunner.setQuantAMMSwapFeeTake(boundFee);
vm.stopPrank();
assertEq(updateWeightRunner.getQuantAMMSwapFeeTake(), boundFee);
assertEq(updateWeightRunner.getQuantAMMUpliftFeeTake(), boundFee);
}

This test passes, confirming that the UpliftFee is being set when setQuantAMMSwapFeeTake is called. This violates the expected independence of the two fees.


Impact

  1. Misrepresentation of Logic:

    • Users or developers interacting with the contract may incorrectly assume that UpliftFee and SwapFee are independently configurable.

  2. Unexpected Behavior:

    • Modifying one fee unintentionally alters the other, potentially disrupting calculations or business logic relying on distinct fee values.

  3. Increased Risk of Errors:

    • Future updates to the contract or dependent systems may introduce further bugs due to this conflation of two seemingly separate variables.


Tools Used

  • Manual code review.

  • Foundry for testing the testSwapFeeSetsUpliftFee behavior.


Recommendations

  1. Separate State Variables:
    Introduce a dedicated state variable for UpliftFee to ensure it is distinct from SwapFee. For example:

    uint256 public quantAMMUpliftFeeTake;
  2. Update setQuantAMMUpliftFeeTake Implementation:
    Modify the setQuantAMMUpliftFeeTake function to manage the new quantAMMUpliftFeeTake variable independently:

    function setQuantAMMUpliftFeeTake(uint256 _quantAMMUpliftFeeTake) external {
    require(msg.sender == quantammAdmin, "ONLYADMIN");
    require(_quantAMMUpliftFeeTake <= 1e18, "Uplift fee must be less than 100%");
    uint256 oldUpliftFee = quantAMMUpliftFeeTake;
    quantAMMUpliftFeeTake = _quantAMMUpliftFeeTake;
    emit UpliftFeeTakeSet(oldUpliftFee, _quantAMMUpliftFeeTake);
    }
  3. Remove Redundancy if Fees Are Intended to Be Identical:
    If the fees are intended to be the same, merge the functions and use a single variable. Update the function names and documentation to reflect this behavior clearly.

Updates

Lead Judging Commences

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

finding_quantAMMSwapFeeTake==quantAMMUplfitFeeTake

Likelyhood: High, calling setters or getters Impact: Low/Medium, both getters return `quantAMMSwapFeeTake` and `setQuantAMMUpliftFeeTake` modify `quantAMMUplfitFeeTake`. Real impact: those 2 values will be always the same.

Support

FAQs

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

Give us feedback!