QuantAMM

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

Owner Fees Collected by `UpliftOnlyExample` Contract Become Inaccessible Due to Missing Withdrawal Feature

Summary

The UpliftOnlyExample contract collects owner fees from swaps but lacks a withdrawal function, causing the accumulated fees in address(this) to be permanently inaccessible.

Vulnerability Details

The fee collection process is implemented in the onAfterSwap function. During swap operations, a portion of the calculated amount (amountCalculatedRaw) is deducted as a fee (hookFee). This fee is split between the quantAMMAdmin (if applicable) and the owner. While the admin's portion is transferred out immediately to their designated address, the owner's portion is sent to the contract itself (address(this)) for accumulation.
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L342-L346

if (ownerFee > 0) {
_vault.sendTo(feeToken, address(this), ownerFee);
emit SwapHookFeeCharged(address(this), feeToken, ownerFee);
}

How Fees Are Handled:

  1. Fee Calculation:
    * The total fee (hookFee) is calculated as a percentage of the amountCalculatedRaw.
    * This fee is divided into two portions:

    • The administrator fee (adminFee), if applicable.

    • The owner fee (ownerFee), which is the remainder of the total fee after deducting the adminFee.

  2. Distribution of Fees:

    • The adminFee is transferred to the administrator's address using the _vault.sendTo function.

    • The ownerFee is transferred to the contract's address (address(this)) and stored there.

Problematic Implementation:

  • While the adminFee is transferred to an external address, the ownerFee is stored in the contract itself.

  • However, the contract lacks any function or mechanism for the owner to withdraw these accumulated fees. Neither the UpliftOnlyExample contract nor its parent contracts implement a withdrawal method.

Impact

All owner fees collected during swap operations are locked in the contract. This is because:

  • The contract address (address(this)) is not externally accessible by default.

  • There are no functions allowing the owner to transfer or withdraw these funds.

Tools Used

VSCode

Recommendations

To resolve this issue, introduce a withdrawal mechanism that allows the owner to retrieve the accumulated fees.

Updates

Lead Judging Commences

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

finding_ownerFee_cannot_be_withdrawn

Likelihood: High, every swap. Impact: High, funds are stuck.

Support

FAQs

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