# Incorrect use of operator leads to arbitrary minting of GVT tokens

Controller.distributeStrategyGainLoss used `||` instead of `&&` in its access check, letting any address pass with index 0 and mint arbitrary GVT via underflow.

- Payout: Audit contest
- Severity: high
- Program: Gro Protocol
- Found by: 0xRajeev
- Disclosed: 2021-08-30
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-06-gro-findings/issues/69
- Library page: https://bugbountylibrary.com/r/c4%3A2021-06-gro%3AH-03
- Tags: area:web3 domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:solidity technique:source-review vuln:access-control vuln:accounting-error

**Target:** Controller.sol / PnL.sol vault adaptor access control
**Root cause:** The require() on L357 used `||` instead of `&&`, so a default mapping value of 0 passes the `<= N_COINS+1` branch; then `index - 1` underflows to uint256_MAX (no SafeMath, solc <0.8.0), routing execution into the Curve LP vault branch.
**Steps:**
1. Attacker (non-vault address) calls `Controller.distributeStrategyGainLoss(ARBITRARY_HIGH_VALUE_OF_GAIN, 0)`
2. `vaultIndexes[msg.sender]` returns 0; `0 > 0` fails but `0 <= N_COINS+1` (0<=4) passes due to `||` on L357
3. L362 `index = index - 1` underflows to `uint256_MAX`
4. L371 `gainUsd = ibuoy.lpToUsd(ARBITRARY_HIGH_VALUE_OF_GAIN)`
5. L376 `ipnl.distributeStrategyGainLoss(gainUsd, lossUsd, reward)`
6. PnL L254 `handleInvestGain(...)` computes `performanceBonus = profit.mul(performanceFee).div(PERCENTAGE_DECIMAL_FACTOR)`
7. PnL L256 `gvt.mint(reward, gvt.factor(gvtAssets), performanceBonus)` mints arbitrary GVT
**How found:** Code review of the access-control predicate on msg.sender in distributeStrategyGainLoss; noticed the `||` operator and traced the default-zero mapping value through the underflow to the mint path.
**Exploitation:** Any external address calls distributeStrategyGainLoss with an arbitrarily large gain value; the underflowed index routes into the Curve LP branch, gain is converted to USD and passed to PnL, which mints GVT performance bonus to the attacker-chosen reward address.
**Insight:** When access control relies on a mapping lookup, check the boolean operator and the default (zero) value path: a `||` between lower/upper bounds lets the default 0 slip through, and a subsequent `-1` on an unsigned index underflows into a privileged branch.

