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

Winner's stats are not updated after a battle

Summary

Missing updates for battleWon property in winner's stats.

Vulnerability Details

After each battle, the winner's OneShot::rapperStats.battlesWon property should be increased to reflect the new battle won.
There is no such update to this winner's stats property.

POC

Put the test excerpt below in `test/OneShotTest.t.sol`
// Test that winner's number of battle won is not increased
function testWinnerStatsNotUpdated(uint256 randomBlock) public twoSkilledRappers {
vm.startPrank(user);
oneShot.approve(address(rapBattle), 0);
cred.approve(address(rapBattle), 3);
console.log("User allowance before battle:", cred.allowance(user, address(rapBattle)));
rapBattle.goOnStageOrBattle(0, 3);
vm.stopPrank();
vm.startPrank(challenger);
oneShot.approve(address(rapBattle), 1);
cred.approve(address(rapBattle), 3);
console.log("User allowance before battle:", cred.allowance(challenger, address(rapBattle)));
// Change the block number so we get different RNG
vm.roll(randomBlock);
vm.recordLogs();
rapBattle.goOnStageOrBattle(1, 3);
vm.stopPrank();
Vm.Log[] memory entries = vm.getRecordedLogs();
// Convert the event bytes32 objects -> address
address winner = address(uint160(uint256(entries[0].topics[2])));
uint256 winnerTokenId = winner == user ? 0 : 1;
IOneShot.RapperStats memory winnerStats = oneShot.getRapperStats(winnerTokenId);
assert(winnerStats.battlesWon == 0);
}

In the terminal, run the following command:

  • forge test --mt testWinnerStatsNotUpdated

Impact

Winners have not seen their stats updated and their number of battle won won't be increased and remain 0 as if they didn't win any battle.
This is unfair and can be really problematic in the future if for example we want to rank rappers and reward them for their performances.

Tools Used

Manual review

Recommendations

Increase the winner's `battlesWon` property in the `OneShot::rapperStats` after each battle.
File: src/RapBattle.sol
function _battle(uint256 _tokenId, uint256 _credBet) internal {
address _defender = defender;
require(defenderBet == _credBet, "RapBattle: Bet amounts do not match");
uint256 defenderRapperSkill = getRapperSkill(defenderTokenId);
uint256 challengerRapperSkill = getRapperSkill(_tokenId);
uint256 totalBattleSkill = defenderRapperSkill + challengerRapperSkill;
uint256 totalPrize = defenderBet + _credBet;
uint256 random =
uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao, msg.sender))) % totalBattleSkill;
// Reset the defender
defender = address(0);
emit Battle(msg.sender, _tokenId, random < defenderRapperSkill ? _defender : msg.sender);
// If random <= defenderRapperSkill -> defenderRapperSkill wins, otherwise they lose
if (random <= defenderRapperSkill) {
// We give them the money the defender deposited, and the challenger's bet
credToken.transfer(_defender, defenderBet);
credToken.transferFrom(msg.sender, _defender, _credBet);
+ IOneShot.RapperStats storage stats = oneShotNft.getRapperStats(defenderTokenId );
+ stats.battlesWon += 1;
} else {
// Otherwise, since the challenger never sent us the money, we just give the money in the contract
credToken.transfer(msg.sender, _credBet);
+ IOneShot.RapperStats storage stats = oneShotNft.getRapperStats(_tokenId);
+ stats.battlesWon += 1;
}
totalPrize = 0;
// Return the defender's NFT
oneShotNft.transferFrom(address(this), _defender, defenderTokenId);
}
Updates

Lead Judging Commences

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

`battlesWon` is never updated

Support

FAQs

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