# crvRewardsContract getReward can be called directly, breaking vaults claimRewards functionallity

Anyone can call Convex BaseRewardPool.getReward for the Amphora Vault, zeroing earned() so Vault.claimRewards mints no AMPH rewards.

- Payout: Contest reward
- Severity: high
- Program: Amphora Protocol
- Credited: said
- Disclosed: 2024-04-22
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-amphora-findings/issues/301
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-amphora%3AH-02
- Tags: domain:web3 impact:dos impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** Vault.claimRewards / Convex BaseRewardPool
**Root cause:** Convex BaseRewardPool.getReward is permissionless and callable for any account, so an attacker can claim the Vault's accrued CRV/CVX before Vault.claimRewards runs; claimRewards reads earned() and skips minting when it is zero.
**Steps:**
1. Vault stakes Curve LP on Convex; rewards accrue, visible via `_rewardsContract.earned(address(vault))`.
2. Attacker calls `BaseRewardPool.getReward(address(vault), false)` directly (permissionless).
3. Rewards are paid out and `earned(vault)` resets to 0.
4. Vault.claimRewards later reads `_crvReward = earned(address(this))` == 0 and skips `_totalCrvReward`/`_totalCvxReward` accumulation, so no AMPH is minted.
**How found:** Code-reading: noticed Convex BaseRewardPool.getReward lacks caller restriction, then traced Vault.claimRewards' dependence on earned() being nonzero.
**Exploitation:** Griefing: attacker repeatedly front-runs or preempts claimRewards by calling getReward on the Vault's behalf, denying users their AMPH reward minting. No capital needed; attacker does not profit directly.
**Insight:** When integrating a third-party rewards contract, check whether its claim function is permissionless for arbitrary accounts; any accounting that reads earned() before claiming can be griefed to zero.
