Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: low
Valid

Defenders can fight against themselves and prevent any defeat

Description

RapBattle::goOnStageOrBattle allows one rapper to be stored in the contract waiting for a battle. The second user calling this function will fight against the rapper on stage. However, nothing prevents defenders from being the second caller of this function and "fight against themselves". In that case, the defender can only win. With this bug, any defender can front-run a challenger who will win to prevent a defeat.

Risk

Likelyhood: High

  • Every time a defender calls the function twice before a different rapper calls it.

Impact: High

  • Defenders always win, which can be used to front-run a defeat in the mempool.

Proof of Concept

Foundry PoC to add in `OneShotTest.t.sol`
function testDefendersCanFightAgainstThemselves() public twoSkilledRappers {
// Rapper go on stage
vm.startPrank(user);
oneShot.approve(address(rapBattle), 0);
cred.approve(address(rapBattle), 3);
rapBattle.goOnStageOrBattle(0, 3);
// Rapper calls the same function to fight against themself
cred.approve(address(rapBattle), 3);
// Won't revert.
rapBattle.goOnStageOrBattle(0, 3);
vm.stopPrank();
}

Recommended Mitigation

Add this require at the top of the else condition:

function goOnStageOrBattle(uint256 _tokenId, uint256 _credBet) external {
if (defender == address(0)) {
...
} else {
require(
+ _tokenId != defenderTokenId,
+ "Defender cannot be also the challenger"
+ );
// credToken.transferFrom(msg.sender, address(this), _credBet);
_battle(_tokenId, _credBet);
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

It's YOU vs YOU

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.