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

Battle emits incorrect winner

Summary

The battle() function emits an incorrect winner value in some cases.

Vulnerability Details

On emit Battle(), the code checks if random is less than defenderRapperSkill, but this is incorrect. It should be checked if it is less than or equal, as indicated later. ("If random <= defenderRapperSkill -> defenderRapperSkill wins")

In this test, we look for a block where random is equal to defenderRapperSkill, and we verify that the winner in that case is incorrect.

function testBattleEmitsIncorrectWinner(uint256 blockNumber) public twoSkilledRappers {
// Initial values
uint256 initialDefenderBalance = cred.balanceOf(user);
// Prepare battle
vm.startPrank(user);
oneShot.approve(address(rapBattle), 0);
cred.approve(address(rapBattle), 3);
rapBattle.goOnStageOrBattle(0, 3);
vm.stopPrank();
vm.startPrank(challenger);
oneShot.approve(address(rapBattle), 1);
cred.approve(address(rapBattle), 3);
vm.stopPrank();
// Init block
vm.assume(blockNumber < type(uint256).max / 12);
vm.roll(blockNumber);
vm.warp(blockNumber * 12);
// Prepare vars
uint256 loop = 0;
uint256 defenderRapperSkill = rapBattle.getRapperSkill(0);
uint256 challengerRapperSkill = rapBattle.getRapperSkill(1);
uint256 totalBattleSkill = defenderRapperSkill + challengerRapperSkill;
address eventWinner;
do {
loop++;
vm.roll(block.number + 1);
vm.warp(block.timestamp + 12);
vm.prevrandao(keccak256(abi.encodePacked(block.number)));
uint256 random = uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, challenger))) % totalBattleSkill;
// If random == defenderRapperSkill, go into battle and get the incorrect winner
if (random == defenderRapperSkill) {
vm.prank(challenger);
vm.recordLogs();
rapBattle.goOnStageOrBattle(0, 3);
Vm.Log[] memory entries = vm.getRecordedLogs();
eventWinner = address(uint160(uint256(entries[0].topics[2])));
break;
}
} while (loop < 1000);
console.log("loops", loop);
// Finally, defender has taken the prize but challenger was emited as the winner
uint256 finalDefenderBalance = cred.balanceOf(user);
assertEq(finalDefenderBalance, initialDefenderBalance + 3);
assertEq(eventWinner, challenger);
}

Test passes

Ran 1 test for test/OneShotTestAudit.t.sol:RapBattleTest
[PASS] testBattleEmitsIncorrectWinner(uint256) (runs: 256, μ: 967301, ~: 940736)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.08s

Impact

Eventually, the event will emit an incorrect winner address, which can negatively affect dapps.

Tools Used

Foundry, Manual review

Recommendations

Correct the event in _battle():

// Reset the defender
defender = address(0);
- emit Battle(msg.sender, _tokenId, random < defenderRapperSkill ? _defender : msg.sender);
+ emit Battle(msg.sender, _tokenId, random <= defenderRapperSkill ? _defender : msg.sender);
}```
Updates

Lead Judging Commences

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

Contradictory battle result event

Support

FAQs

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