# Insufficient access control in the batchActionsOnSwappers() function

InfinityPoolsPeriphery.batchActionsOnSwappers only checks operator approval on the first tokenId, letting an operator approved for one NFT reflow/unwind all of the owner's positions.

- Payout: Contest reward
- Severity: high
- Program: InfinityPools
- Credited: Spearmint
- Disclosed: 2025-01-13
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_infinitypools_october2024.pdf#3.1.4
- Library page: https://bugbountylibrary.com/r/cantina%3Ainfinitypools_october2024%3A3.1.4
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:auth-bypass

**Target:** InfinityPoolsPeriphery.batchActionsOnSwappers
**Root cause:** The batch loop verifies msg.sender is approved/operator only for the first tokenId, then for subsequent tokenIds merely checks that the owner matches, never calling isApprovedForAll per token.
**Steps:**
1. Alice opens multiple swapper positions (newLoan) and approves Bob as operator for only tokenId #1 via `infinityPoolsPeriphery.approve(bob, id1)`.
2. Bob builds `ReflowParams[]` containing id1 (approved) plus id2..id5 (not approved) and empty unwind/newLoan arrays.
3. Bob calls `infinityPoolsPeriphery.batchActionsOnSwappers(unwindTokenIds, reflowParams, newLoanParams, swapInfo)`.
4. Call succeeds and reflows all five of Alice's positions despite approval only on id1.
**How found:** Read the docs' permission guarantee (owner or NFT operator only) and compared it to the batch function's loop, noticing the approval check was hoisted out of the per-tokenId loop and replaced by an owner-equality check.
**Exploitation:** A user granted operator rights over a single position can invoke any swapper action (reflow, unwind, newLoan) on every other position owned by the same owner, altering or closing positions without authorization.
**Insight:** In batch functions that loop over tokenIds, verify authorization inside the loop per id; a single upfront approval check on the first element is a common pattern that silently authorizes the rest.
