Beginner FriendlyFoundryGameFi
100 EXP
View results
Submission Details
Severity: low
Invalid

Any user can call `MartenitsaVoting::voteForMartenitsa` function , allowing a Malicious user to create multiple aliases and rig voting to become winner and claim `healthtoken`

Summary

Once the voting period starts and address can vote i.e call MartenitsaVoting::voteForMartenitsa which can be exploited by a malicious user to create multiple aliases and rig voting to become winner

Impact

Any malicious user can create multiple aliases and rig voting to become winner since creating multiple wallets or smartcontracts is trivial.

Proof of Concept

Note: Please Import {console} in MartenitsaVoting.t.sol by adding import {console} from "forge-std/Test.sol"; at the top for the PoC's to work effortlessly.

Malicious user jack creates 50 other aliases to win the voting and claim the healthToken

PoC: Malicious User Multiple Aliases To Win Vote
function testMaliciousUserMultipleAliasesToWinVote() public startVoting {
vm.startPrank(jack);
martenitsaToken.createMartenitsa("bracelet");
marketplace.listMartenitsaForSale(0, 1 wei);
vm.stopPrank();
vm.startPrank(chasy);
martenitsaToken.createMartenitsa("bracelet");
marketplace.listMartenitsaForSale(1, 1 wei);
vm.stopPrank();
vm.prank(bob);
voting.voteForMartenitsa(1);
vm.prank(jack);
voting.voteForMartenitsa(0);
// Jack Creating 50 aliases to win the vote
uint256 extrausers = 50;
for (uint256 i = 0; i < extrausers; i++) {
string memory x = string(abi.encodePacked(i));
address user = makeAddr(x);
vm.startPrank(user);
voting.voteForMartenitsa(0);
vm.stopPrank();
}
console.log("Vote Count 0 :", voting.getVoteCount(0));
console.log("Vote Count 1 :", voting.getVoteCount(1));
vm.warp(block.timestamp + 1 days);
address owner = address(0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496);
vm.prank(owner);
voting.announceWinner();
}

Recommendations

Adding a requirement to the MartenitsaVoting::voteForMartenitsa function that only users who are owners of MartenitsaToken can vote will mitigate the issue, i can be implemented in the following manner:

  1. Import MartenitsaToken.sol in MartenitsaVoting.sol

import {MartenitsaToken} from "./MartenitsaToken.sol";

  1. Create a State variable named _martenitsaToken in MartenitsaVoting contract

MartenitsaToken public _martenitsaToken;
  1. Initialize _martenitsaToken inMartenitsaVoting::constructor and update testsuites to use the new constructor

constructor(address marketplace, address healthToken , address martenitsaToken) Ownable(msg.sender) {
_martenitsaMarketplace = MartenitsaMarketplace(marketplace);
_healthToken = HealthToken(healthToken);
_martenitsaToken = MartenitsaToken(martenitsaToken);
}
  1. Now finally add the following statement to the MartenitsaVoting::voteForMartenitsa function

+ require (_martemitsaToken.balanceOf(msg.sender) != 0 , "Cannot Vote without owning a Martenitsa")
Updates

Lead Judging Commences

bube Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

Multiple addresses

Support

FAQs

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