QuantAMM

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

Uplift Fee and Swap Fee Share Same State Variable

Description

In UpdateWeightRunner.sol, both the uplift fee and swap fee mechanisms incorrectly use the same state variable quantAMMSwapFeeTake. This prevents the protocol from implementing different fee structures for swap and uplift operations, potentially leading to revenue loss and economic model disruption.

Vulnerable Code

// Single state variable used for both fees
uint256 public quantAMMSwapFeeTake = 0.5e18;
// Swap fee setter
function setQuantAMMSwapFeeTake(uint256 _quantAMMSwapFeeTake) external override {
require(msg.sender == quantammAdmin, "ONLYADMIN");
require(_quantAMMSwapFeeTake <= 1e18, "Swap fee must be less than 100%");
uint256 oldSwapFee = quantAMMSwapFeeTake;
quantAMMSwapFeeTake = _quantAMMSwapFeeTake;
emit SwapFeeTakeSet(oldSwapFee, _quantAMMSwapFeeTake);
}
// Uplift fee setter - incorrectly uses swap fee variable
function setQuantAMMUpliftFeeTake(uint256 _quantAMMUpliftFeeTake) external {
require(msg.sender == quantammAdmin, "ONLYADMIN");
require(_quantAMMUpliftFeeTake <= 1e18, "Uplift fee must be less than 100%");
uint256 oldSwapFee = quantAMMSwapFeeTake;
quantAMMSwapFeeTake = _quantAMMUpliftFeeTake; // Bug: overwrites swap fee
emit UpliftFeeTakeSet(oldSwapFee, _quantAMMUpliftFeeTake);
}
// Uplift fee getter - returns swap fee instead
function getQuantAMMUpliftFeeTake() external view returns (uint256) {
return quantAMMSwapFeeTake; // Bug: returns swap fee
}

Impact

HIGH severity due to:

  • Protocol cannot maintain separate fee structures for different operations

  • Setting one fee automatically overwrites the other

  • Protocol loses revenue when a higher fee is overwritten by a lower fee

  • Users may be charged incorrect fees

Proof of Concept

// Initial state
setQuantAMMSwapFeeTake(0.5e18); // Set swap fee to 0.5%
assert(getQuantAMMSwapFeeTake() == 0.5e18); // Passes
setQuantAMMUpliftFeeTake(1e18); // Set uplift fee to 1%
assert(getQuantAMMUpliftFeeTake() == 1e18); // Passes
assert(getQuantAMMSwapFeeTake() == 1e18); // Passes - swap fee was overwritten!

Tools Used

  • Manual code review

  • Static analysis

Recommendations

  1. Separate State Variables

uint256 public quantAMMSwapFeeTake = 0.5e18;
uint256 public quantAMMUpliftFeeTake = 0.5e18; // New variable
  1. Fix Uplift Fee Setter

function setQuantAMMUpliftFeeTake(uint256 _quantAMMUpliftFeeTake) external {
require(msg.sender == quantammAdmin, "ONLYADMIN");
require(_quantAMMUpliftFeeTake <= 1e18, "Uplift fee must be less than 100%");
uint256 oldUpliftFee = quantAMMUpliftFeeTake; // Use correct variable
quantAMMUpliftFeeTake = _quantAMMUpliftFeeTake; // Set correct variable
emit UpliftFeeTakeSet(oldUpliftFee, _quantAMMUpliftFeeTake);
}
  1. Fix Uplift Fee Getter

function getQuantAMMUpliftFeeTake() external view returns (uint256) {
return quantAMMUpliftFeeTake; // Return correct variable
}
Updates

Lead Judging Commences

n0kto Lead Judge 7 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.