# Reward distribution may be vulnerable to sandwich attacks

Aquarius router snapshots pool liquidity in fill_liquidity, letting an attacker flash-loan liquidity into a low-fee pool to capture a disproportionate share of rewards.

- Payout: Contest reward
- Severity: medium
- Program: Aquarius
- Credited: shaflow01
- Disclosed: 2025-09-01
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_aquarius_aug2025.pdf#3.2.1
- Library page: https://bugbountylibrary.com/r/cantina%3Aaquarius_aug2025%3A3.2.1
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:medium tech:solidity technique:race-window vuln:business-logic vuln:flash-loan vuln:reward-distribution

**Target:** Soroban liquidity pool router reward configuration (fill_liquidity/config_pool_rewards)
**Root cause:** Reward allocation across fee-tier pools is computed from a single instantaneous liquidity snapshot taken in fill_liquidity, rather than a time-weighted measure, so liquidity can be temporarily inflated.
**Steps:**
1. Admin calls `config_global_rewards` to set reward weights per token pair.
2. Attacker flash-loans tokens and calls `router.deposit` into the low-fee pool (e.g. 10 bps) to inflate its liquidity.
3. Attacker calls `router.fill_liquidity(&tokens)` so the inflated ratio is recorded.
4. Attacker calls `router.withdraw` to remove the added liquidity and repays the flash loan.
5. Admin calls `config_pool_rewards`, which divides rewards by the recorded ratio, over-allocating to the manipulated pool (PoC: 95663 vs 4336).
**How found:** Reviewer read the reward configuration flow (config_global_rewards → fill_liquidity → config_pool_rewards) and noticed allocation depends solely on the liquidity ratio captured at fill_liquidity time, which is manipulable.
**Exploitation:** Attacker with existing liquidity in a low-fee pool front-runs the admin's fill_liquidity call: flash-loan tokens, deposit to inflate that pool's share, trigger fill_liquidity, withdraw and repay, then collect inflated reward rate after config_pool_rewards.
**Insight:** When a protocol snapshots state for later rate/weight computation, check whether that snapshot can be moved by a single transaction (flash loan, deposit/withdraw) between snapshot and use; time-weighted or admin-gated snapshots close this.
