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

`MartenitsaVoting::voteForMartenitsa` lets users to vote before voting period actually starts

Summary

MartenitsaVoting::voteForMartenitsa misses to enforce that users can only vote after the voting has actually started. Consequently, users can start voting before the protocol owner would officially kick of voting by calling MartenitsaVoting::startVoting.

Vulnerability Details

MartenitsaEvent::voteForMartenitsa is supposed to enable users to vote for listed Martenitsa NFTs within a predefined voting period. Voting period starts when the protocol owner calls MartenitsaVoting::startVoting. In this same call, the duration and, hence, the end of the period is also defined.

MartenitsaEvent::voteForMartenitsa correctly check whether the voting period has already ended or not, and if ended, does not allow more votes. It is, however, misses to check whether the voting period has actually started and, hence, users can start voting any time right after the creation of the contract.

This is demonstarted in the proof of code below:

Proof of Code
function testCanVoteBeforeVotingStarts() public {
address user = makeAddr("user");
uint256 price = 1 ether;
// jack produces an NFT, lists it
vm.startPrank(jack);
martenitsaToken.createMartenitsa("bracelet");
martenitsaToken.approve(address(marketplace), 0);
marketplace.listMartenitsaForSale(0, price);
vm.stopPrank();
// user votes before voting starts
vm.prank(user);
voting.voteForMartenitsa(0);
assert(voting.getVoteCount(0) == 1);
// voting starts
voting.startVoting();
// early vote still counts
assert(voting.getVoteCount(0) == 1);
}

Impact

  • Users can start voting before the start of the actual voting period.

  • Martentisa NFT owners noticing and exploiting this bug can get an unfair advantage in the voting: they will have more time to get and/or generate votes for their own listed NFTs. With this unfair advantage they can get the healthToken rewards reserved for the winner of the vote.

Tools Used

Manual review, Foundry.

Recommendations

Implement a check in MartenitsaVoting::voteForMartenitsa so that users will not be able to vote before the voting actually starts:

function voteForMartenitsa(uint256 tokenId) external {
+ require(block.timestamp >= startVoteTime, "Voting is not active yet");
require(!hasVoted[msg.sender], "You have already voted");
require(block.timestamp < startVoteTime + duration, "The voting is no longer active");
list = _martenitsaMarketplace.getListing(tokenId);
require(list.forSale, "You are unable to vote for this martenitsa");
hasVoted[msg.sender] = true;
voteCounts[tokenId] += 1;
_tokenIds.push(tokenId);
}
Updates

Lead Judging Commences

bube Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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