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

`RapperStats.battlesWon` is not used across the system

Vulnerability Details

RapperStats.battlesWon is not incremented after winning a battle in RapBattle.goOnStageOrBattle.

Impact

The information provided in OneShot.getRapperStats does not reflect correctly rapper metadata. This can lead to misconceptions by users about the status of their rappers.

Tools Used

Manual review.

Recommendations

Make the following changes in contract IOneShot.sol:

https://github.com/Cyfrin/2024-02-one-shot/blob/main/src/interfaces/IOneShot.sol

interface IOneShot is IERC721 {
struct RapperStats {
bool weakKnees;
bool heavyArms;
bool spaghettiSweater;
bool calmAndReady;
uint256 battlesWon;
}
// Mint a new rapper token
function mintRapper() external;
// Add functions for direct metadata manipulation
function getRapperStats(uint256 tokenId) external view returns (RapperStats memory);
// Update metadata for a token
function updateRapperStats(
uint256 tokenId,
bool weakKnees,
bool heavyArms,
bool spaghettiSweater,
bool calmAndReady,
uint256 battlesWon
) external;
+ function increaseRapperBattlesWon(uint256 tokenId) external;
}

Make the following changes in contract OneShot.sol:

https://github.com/Cyfrin/2024-02-one-shot/blob/47f820dfe0ffde32f5c713bbe112ab6566435bf7/src/OneShot.sol#L13

+ address private _rapButtleContract;

https://github.com/Cyfrin/2024-02-one-shot/blob/47f820dfe0ffde32f5c713bbe112ab6566435bf7/src/OneShot.sol#L28

+function setRapButtleContract(address rapButtleContract) public onlyOwner {
+ require(rapButtleContract != address(0));
+ _rapButtleContract = rapButtleContract;
+}
+
+modifier onlyRapButtleContract() {
+ require(msg.sender == address(_rapButtleContract), "Not the RapButtle contract");
+ _;
+}

https://github.com/Cyfrin/2024-02-one-shot/blob/47f820dfe0ffde32f5c713bbe112ab6566435bf7/src/OneShot.sol#L53

+function increaseRapperBattlesWon(uint256 tokenId) external onlyRapButtleContract {
+ require(tokenId < _nextTokenId, "Wrong tokenId");
+ RapperStats storage metadata = rapperStats[tokenId];
+ metadata.battlesWon += 1;
+}

Make the following changes in contract RapBattle.sol :

https://github.com/Cyfrin/2024-02-one-shot/blob/47f820dfe0ffde32f5c713bbe112ab6566435bf7/src/RapBattle.sol#L54C1-L81C6

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);
+ oneShotNft.increaseRapperBattlesWon(random <= defenderRapperSkill ? defenderTokenId : _tokenId);
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);
} else {
// Otherwise, since the challenger never sent us the money, we just give the money in the contract
credToken.transfer(msg.sender, _credBet);
}
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.