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

Sybil attack on `mintRapper` defeats the purpose of staking and rap battle

Summary

Sybil attack on mintRapper defeats the purpose of staking and rap battle.

Vulnerability Details

Users can use sybil attack to farm credTokens.

Attack Scenario -

  1. A user mints multiple rappers from the same address.

  2. Each rapper can stake for 1 day.

  3. Unstaking after 1 day, user can transfer all rapper's credTokens to a single rapper.

This way, the user can get large amount of credTokens in 1 day without any limit of 1 credToken/day set by the protocol.

This severity can further be exploited by betting a large amount of credTokens in goOnStageOrBattle function such that other users will also need to use sybil attack to accumulate the required credTokens and then only can they participate in rap battles.

Impact

  1. Users can always mint more credTokens without staking limit and battles. This will make the whole purpose of rap battles and bets pointless.

  2. Users only need to stake for 1 day to break the staking limits. This will shift the focus of users and force them to using sybil attack to interact with the protocol.

Due to the nature of blockchain, even after this bug is fixed, users can still exploit this contract using factory contract and creating more addresses to repeat this sybil attack. Many different fixes will be required such as -

  1. Fixing this issue (by restricting 1 rapper per 1 address)

  2. Setting a limit to betting rap battles. Rap Battles can be made into different battles such as small rap battles will require smaller bets. Bigger battles will require bigger bets and a minimum number of battles won by the participants to participate.

  3. Adding a minimal cost to mint Rapper NFT.

All these fixes can be used together to minimize the sybil attacks effects on the protocol.

Tools Used

Manual Review

Recommendations

Add the below code in OneShot contract -

+ mapping(address => bool) public rapperminted;
function mintRapper() public {
+ require(!rapperminted(msg.sender); "rapper already minted");
uint256 tokenId = _nextTokenId++;
_safeMint(msg.sender, tokenId);
rapperminted(msg.sender) = true;
// Initialize metadata for the minted token
rapperStats[tokenId] = RapperStats({
weakKnees: true,
heavyArms: true,
spaghettiSweater: true,
calmAndReady: false,
battlesWon: 0
});
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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