QuantAMM

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

Owner fees get's locked in UpliftOnlyExample.sol forever

Summary

After swap in Vault , the Vault call UpliftOnlyExample.sol#onAfterSwap for the purpose of fees deduction . The fees for Quant Amm Admin is transferred to the admin but the fees for UpliftOnlyExample owner stays in the contract and the contract has no function to withdraw the fees out .

Vulnerability Details

UpliftOnlyExample.sol is a router contract which is used to add/remove from the Vaults . It has some callback functions activated for the hooks as can be seen :
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L372-L384

function getHookFlags() public pure override returns (HookFlags memory) {
HookFlags memory hookFlags;
// `enableHookAdjustedAmounts` must be true for all contracts that modify the `amountCalculated`
// in after hooks. Otherwise, the Vault will ignore any "hookAdjusted" amounts, and the transaction
// might not settle. (It should be false if the after hooks do something else.)
hookFlags.enableHookAdjustedAmounts = true;
hookFlags.shouldCallBeforeAddLiquidity = true;
hookFlags.shouldCallAfterRemoveLiquidity = true;
hookFlags.shouldCallAfterSwap = true;
return hookFlags;
}

One of the callbacks amongst them is onAfterSwap , which is called after swaps in Vault for deduction Quant AMM Admin fees and Owner fees of the UpliftOnlyExample contract as can be seen here :
https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol#L292-L295

/// @inheritdoc BaseHooks
function onAfterSwap(
AfterSwapParams calldata params
) public override onlyVault returns (bool success, uint256 hookAdjustedAmountCalculatedRaw) {

The problem in the function is that the fees for the Owner is deducted from the amount used in swap correctly and is transferred to the UpliftOnlyExample contract correctly :

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

if (ownerFee > 0) {
_vault.sendTo(feeToken, address(this), ownerFee);/* <@audit */
emit SwapHookFeeCharged(address(this), feeToken, ownerFee);
}
}

https://github.com/Cyfrin/2024-12-quantamm/blob/a775db4273eb36e7b4536c5b60207c9f17541b92/pkg/vault/contracts/Vault.sol#L158-L163

function sendTo(IERC20 token, address to, uint256 amount) external nonReentrant onlyWhenUnlocked {
_takeDebt(token, amount);
_reservesOf[token] -= amount;
token.safeTransfer(to, amount);
}

but the UpliftOnlyExample contract has no withdraw function enabled for the Owner to withdraw the fee tokens out of the contract, thereby locking the fee tokens permanently in the contract .

Impact

Owner fees get's locked in the contract forever .

Tools Used

Manual Review

Recommendations

Add a access restricted withdraw function in the UpliftOnlyExample contract for the Owner to withdraw the fees out

Updates

Lead Judging Commences

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