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

```RapBattle::_battle``` challenger missing approval for token transfer

Summary

In the RapBattle::_battle function when a defender wins a battle, the contract attempts to transfer the challenger's wagered CRED tokens to the defender. However, the contract does not ensure that the challenger has approved the RapBattle contract to transfer their CRED tokens on their behalf, leading to a failure in executing the token transfer. The defender doesn't receive the prize.

Vulnerability Details

The vulnerability arises from the use of the transferFrom function without prior assurance that the necessary approval has been granted by the token owner (the challenger in this context). The ERC-20 token standard requires that transferFrom can only be successfully called if the token owner has explicitly approved the spender (in this case, the RapBattle contract) to withdraw tokens up to a certain amount.

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);
} 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);
}

Impact

If the challenger has not approved the RapBattle contract to transfer their CRED tokens, the contract's attempt to transfer the wagered tokens to the defender (in the event of the defender's victory) will fail.

Tools Used

Manual review

Recommendations

It is recommended to implement a mechanism that ensures challengers have approved the RapBattle contract to transfer their wagered CRED tokens before they can participate in a battle.

Updates

Lead Judging Commences

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

missing check for sufficient `_credBet_` approval

Support

FAQs

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