Function goOnStageOrBattle in contract RapBattle if defender != address(0) do not check that msg.sender is owner of rapper with _tokenId.
Assume that defender in the RapBattle contract equals address(0), which means that there is no one on stage right now.
1 First user call RapBattle.goOnStageOrBattle with his own rapper.
2 Attacker call RapBattle.goOnStageOrBattle with some rapper with RapBattle.getRapperSkill equal 75.
3 Function _battle in the RapBattle contract then do incorrect computations of winner:
3.1 challengerRapperSkill manipulated by attacker up to 25 points
3.2 totalBattleSkill depends on challengerRapperSkill :
3.3 random is in [0, totalBattleSkill) :
3.4 chance to win depends on totalBattleSkill :
assume defenderRapperSkill equal 50 this means:
in the situation where attacker uses most skilled rapper without owning him with challengerRapperSkill equal 75:
defender win in 50 from 125 randoms => 40% chance to win
in the situation where attacker uses just minted rapper with challengerRapperSkill equal 50:
defender win in 50 from 100 randoms => 50% chance to win
It allows any user to take part in a battle without owning a rapper and choose the rapper with the biggest skill returned from RapBattle.getRapperSkill.
This leads to improve his chances to win up to 10%.
Manual review.
Make the following changes in RapBattle.goOnStageOrBattle
https://github.com/Cyfrin/2024-02-one-shot/blob/47f820dfe0ffde32f5c713bbe112ab6566435bf7/src/RapBattle.sol#L38C1-L52C6
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.