When a user tries to enter a battle as challenger (2nd player), RapBattle::goOnStageOrBattle
does check whether said user actually has the CRED
balance to cover the bet amount, nor does it check whether said user has the NFT with the submitted ID. Conseqently, challengers can battle without having a rapper NFT, and without actually having any balance in CRED
tokens.
To participate in a battle, users need to call RapBattle::goOnStageOrBattle
and as arguments to this function, they need to provide
(1) the ID of one of their rapper NFTs and
(2) the amount of CRED
tokens they intend to wager.
However,goOnStageOrBattle
does not perform the neccessary input validation when a challenger (2nd player) tries to enter the battle. As a result, challengers can battle without having a rapper NFT, and without actually having any kind of balance in CRED
tokens. This oversight undermines the fairness and integrity of battles, allowing challengers to participate risk-free,
The challenger can cheat the system and is in an unfair advantage. Having a zero balance of CRED
, the challenger does not actually risk any funds when entering a battle, hence cannot lose. Since the defender has no option to withdraw from the battle once entered on the stage, the challenger can keep the defender "hostage" and keep battling it until chance turns to the challenger's favor so that the challenger wins.
Consider the following scenario:
Defender calls RapBattle::goOnStageOrBattle
, and submits (1) the ID of one of its (not staked) rapper NFTs and (2) some amount of its CRED
balance as a bet.
Defender's NFT and amount of CRED
tokens submitted to the battle are transferred to RapBattle
.
Challenger calls RapBattle::goOnStageOrBattle
, but submits the ID of an NFT that he does not actually own, and submits the same bet amount as the defender without actually having any balance of CRED
.
Assuming that the defender wins the battle, the challenger cannot pay up since it has a zero balance of CRED
. The transaction (where the challenger entered the battle) reverts. Defender's NFT and bet is stuck in the RapBattle
contract.
Challenger enters the battle again, the same way as in point 3.
Assuming that this time the challenger wins the battle, the defender's bet amount is transferred to the challenger.
Defender's NFT is finally transferred back to the defender.
Insert the following piece of code in OneShotTest.t.sol
:
and test it by executing forge test --mt test_challengerCanBattleWithoutHavingAnNftOrCredTokens
.
Output:
Manual review, Foundry
Before starting the battle, check that the challenger
actually has the NFT belonging to the ID he submitted to the battle.Before starting the battle, and
has enough CRED
balance to cover the bet.
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.