An EOA who does not hold a OneShot NFT or any CRED tokens can enter into a battle with a legitimate OneShot NFT holder and, if they win the battle, will receive the bet placed by the legitimate OneShot NFT holder.
The functions RapBattle::goOnStageOrBattle
and RapBattle::_battle
have design or coding flaws which permit a non-NFT holder with no balance of CRED to enter into a rap battle and collect winnings. Neither function validates that the 2nd battle entrant ("challenger") is a legitimate NFT holder or holds enough CRED to cover their bet.
Additionally, the challenger does not have their bet collected in advance or their NFT transferred to the RapBattle contract, as is done for the 1st entrant ("defender").
High - Impact is high as this would devalue the utility of owning a OneShot NFT as a non-owner can battle and collect winnings. Likelihood is also high as any EOA could execute this attack by calling RapBattle::goOnStageOrBattle
.
Visual Studio Code, Foundry, manual review
Add the following test function to OneShotTest.s.sol:
Execute the test until it passes, this could take multiple runs. Passing indicates that the nonOwner was able to collect winnings from a battle.
There are several ways to correct this vulnerability. The approach described below will prevent a non-owner from entering battle and would also prevent an owner with insufficient CRED from entering battle.
The comment line preceding the call to RapBattle::_battle
, if uncommented, could prevent the challenger from betting an amount of CRED they don't hold as it will revert. However, enforcing this through the require function as shown also allows it to be applied to the defender and is done earlier which will save gas for callers.
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.