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

The same Martenitsa can be used multiple time to collect the reward

Summary

In MartenitsaMarketplace::collectReward the same Martenitsa can be used multiple time to collect the reward

Impact

A malicious user can collect the reward, gift the Martenitsa to another address and collect again the reward as many time as he wants.
This give the ability to mint an infinite amount of HealthToken

Proof of Concept:
Add this test in MartenitsaMarketplace.t.sol:

Proof Of Code
function testCanCollectRewardMultipleTimes() public eligibleForReward {
vm.startPrank(bob);
marketplace.collectReward();
vm.stopPrank();
assert(healthToken.balanceOf(bob) == 10 ** 18);
// bob gift the Martenitsa to his second wallet to claim a second time
address secondBobAddress = makeAddr("secondBob");
vm.startPrank(bob);
martenitsaToken.approve(address(marketplace), 0);
martenitsaToken.approve(address(marketplace), 1);
martenitsaToken.approve(address(marketplace), 2);
marketplace.makePresent(secondBobAddress, 0);
marketplace.makePresent(secondBobAddress, 1);
marketplace.makePresent(secondBobAddress, 2);
vm.stopPrank();
vm.startPrank(secondBobAddress);
marketplace.collectReward();
vm.stopPrank();
assert(healthToken.balanceOf(secondBobAddress) == 10 ** 18);
}

Tools Used

Foundry

Recommendations

Add a mapping that track which Martenitsa are already been used in MartenitsaMarketplace

contract MartenitsaMarketplace is Ownable {
...
mapping(address => uint256) private _collectedRewards;
mapping(uint256 => Listing) public tokenIdToListing;
+ mapping
...
- function collectReward() external {
+ function collectReward(uint256[] memory martenitsaTokens) external {
require(!martenitsaToken.isProducer(msg.sender), "You are producer and not eligible for a reward!");
+ for (uint256 i = 0; i < martenitsaTokens.length; i++) {
+ require(!_alreadyUsedMartenitsa[martenitsaTokens[i]], "one token is already used");
+ _alreadyUsedMartenitsa[martenitsaTokens[i]] = true;
+ }
+ uint256 amountRewards = martenitsaTokens.length / requiredMartenitsaTokens;
- uint256 count = martenitsaToken.getCountMartenitsaTokensOwner(msg.sender);
- uint256 amountRewards = (count / requiredMartenitsaTokens) - _collectedRewards[msg.sender];
if (amountRewards > 0) {
_collectedRewards[msg.sender] = amountRewards;
healthToken.distributeHealthToken(msg.sender, amountRewards);
}
}
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.