# AgentDAO::_castVote doesn’t check the array of votes emitted, which determine the number of battles fought in EloCalculator.sol, allowing the user to increase the ELO of a contribution unfairly, inflating the maturity/impact of ServiceNFTs

AgentDAO._castVote passes unvalidated vote array length to EloCalculator.battleElo, letting a voter inflate a ServiceNFT's ELO/maturity and skew contributor rewards.

- Payout: Contest reward
- Severity: medium
- Program: Virtuals Protocol
- Credited: Jeremias
- Disclosed: 2025-08-04
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-04-virtuals-protocol#m-11
- Library page: https://bugbountylibrary.com/r/c4%3A2025-04-virtuals-protocol%3AM-11
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** AgentDAO._castVote / EloCalculator.battleElo (Solidity contracts)
**Root cause:** _updateMaturity decodes params into a uint8[] votes array and passes it to battleElo without checking its length, so the number of Elo battles is attacker-controlled rather than fixed at 10.
**Steps:**
1. Call `castVoteWithReasonAndParams(proposalId, 1, reason, abi.encode(uint8[]))` with a votes array longer than 10, all values mapping to a win.
2. _castVote forwards params to `_updateMaturity`, which `abi.decode`s the array without a length check.
3. `_calcMaturity` calls `EloCalculator.battleElo(maturity, votes)`, iterating once per array element.
4. Each iteration raises eloA, so returned maturity = currentRating + eloA - 1000 grows unbounded with array length.
5. `_proposalMaturities[proposalId] += maturity * weight` inflates stored maturity, which `updateImpact` and reward distribution consume.
**How found:** Compared whitepaper's fixed 10-round Elo validation against code; noticed params bytes flow unchecked from _castVote into battleElo's loop bound.
**Exploitation:** A contributor or voter submits a single on-chain vote with an oversized uint8[] of winning results, inflating the proposal's maturity and resulting ServiceNFT impact, which feeds AgentReward v1/v2 contributor reward calculations for excess payout.
**Escalation:** Inflated maturity propagates to ServiceNFT impact, which is used as reward weight in AgentReward v1/v2, amplifying payout beyond fair share.
**Insight:** When a spec fixes a count (e.g. 10 rounds), grep for every loop bound and array length derived from user-supplied bytes params; off-chain-specified constants often lack on-chain enforcement.
