# Adversary can abuse hanging approvals left by PSwapLib.swap to bypass reward fees

AuraSpell/ConvexSpell let users set arbitrary expectedRewards, leaving hanging token approvals that allow swapping reward tokens out of order to bypass reward fees.

- Payout: Contest reward
- Severity: medium
- Program: Blueberry
- Credited: 0x52
- Disclosed: 2023-07-12
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-07-blueberry-judging/issues/104
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-07-blueberry%3AM-7
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:fee-bypass

**Target:** AuraSpell/ConvexSpell closePositionFarm reward swap via PSwapLib
**Root cause:** closePositionFarm accepts user-controlled expectedRewards and swapDatas, and PSwapLib.swap approves the sellToken amount without resetting after the swap, leaving residual allowances. Users can swap reward tokens in arbitrary order relative to _doCutRewardsFee.
**Steps:**
1. Redeem a tiny amount of LP with expectedRewards set to uint256.max for both reward tokens A and B, but do not actually sell, leaving large hanging approvals.
2. Withdraw the remaining position, specifying swapDatas to swap token B first.
3. Observe flow becomes RewardCut A > Swap B > RewardCut B > Swap A, so token B is swapped before its fee cut, bypassing the fee.
**How found:** Code review of AuraSpell#closePositionFarm noting user-controlled expectedRewards and swapDatas, and that PSwapLib.swap resets approval before but not after the swap, leaving residual allowance; realized swap order is user-chosen so fee cut order can be subverted.
**Exploitation:** Attacker first creates hanging approvals by redeeming minimal LP with expectedRewards=uint256.max and skipping the swap, then on full withdrawal reorders swapDatas so a reward token is swapped before _doCutRewardsFee applies to it, avoiding the reward fee on that token.
**Insight:** When a contract approves a user-specified amount for a user-specified external call and only resets before (not after), residual allowances persist; also check whether fee/accounting steps assume a fixed ordering of user-controllable swap calls.
