Beginner FriendlyFoundryGameFi
100 EXP
View results
Submission Details
Severity: medium
Valid

`MartenitsaEvent` is an Independent NFT Collection Not Compatible with the Rest of the Protocol

Summary

MartenitsaEvent manages special events users can join with HealthToken tokens claimed after acquiring 3 different Martenitsa. After a user has joined an event they get the producer role while the event is active, this will allow them to create Martenitsa and sell them in the Marketplace, but nothing of this is possible for the following reasons:

  • MartenitsaEvent is a unique and independent NFT collection that is not compatible with the rest of the protocol. This means Martetnisa created via MartenitsaEvent cannot be sold nor cannot be used to claim rewards from the marketplace and cannot participate in the voting system.

  • the producer role is assigned to the user in MartenitsaEvent but not in MartenitsaToken thus not giving them the ability to create Martenitsa nor list them for sale

Vulnerability Details

Let's say Chasy creates and list three Martenitsa minted via MartenitsaToken and the marketplace, later Bob purchases all tokens; Bob who is interested in joining an upcoming event claims the reward from the marketplace. The owner starts an event which Bob enter, now Bob decides to create a Martenitsa from MartenitsaEvent and decides to list it for sale but for Bob surprise he can't. Bob tries to create a Martenitsa via MartenitsaToken is not possible because the producer roles has not been given to him.

Eventually Bob realizes his Martenitsa belongs to a collection that is independent and incompatible from the rest of the protocol.

The above can be verified in the following proof of concept:

PoC
function testSecurityReview__IncompatibleCollection() public {
// chasy a produces, creates and list three Martenitsa for sale
for (uint256 i; i < 3; i++) {
vm.startPrank(chasy, chasy);
martenitsaToken.createMartenitsa("bracelet");
martenitsaToken.approve(address(marketplace), i);
marketplace.listMartenitsaForSale(i, 1 wei);
vm.stopPrank();
}
vm.startPrank(bob, bob);
// bob buys all tokens
for (uint256 i; i < 3; i++) {
marketplace.buyMartenitsa{value: 1 wei}(i);
}
// bob collect rewards
marketplace.collectReward();
vm.stopPrank();
// event starts
martenitsaEvent.startEvent(1000);
vm.startPrank(bob, bob);
// bob joins event
healthToken.approve(address(martenitsaEvent), type(uint256).max);
martenitsaEvent.joinEvent();
// Bob becomes a producer in `MartenitsaEvent` and not in `MartenitsaToken`
vm.expectRevert("You are not a producer!");
martenitsaToken.createMartenitsa("bracelet");
martenitsaEvent.createMartenitsa("bracelet");
// Bob cannot list Martenitsa for sale bc producer role is not assigned in `MartenitsaToken`
vm.expectRevert("You are not a producer!");
marketplace.listMartenitsaForSale(0, 1 wei);
vm.stopPrank();
}

Impact

Key functionality of the protocol broken, rewarded users do not become producers and cannot participate in the rest of the protocol as expected.

Tools Used

Manual review, Foundry

Recommendations

To fix this issue at least MartenistaEvent and MartnitesaToken needs refactoring, I'll list a few recommendations:

  • Instead of MartenitsaEvent inheriting MartenitsaToken, pass the address as a constructor parameter so when a user joins the event the contract makes external calls to read and write to the token contract.

  • Create entry in MartenitsaToken for MartenitsaEvent so it can be possible to write to MartenitsaToken::producers.

Updates

Lead Judging Commences

bube Lead Judge
over 1 year ago
bube Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

MartenitsaToken and MartenitsaEvent have different addresses

Support

FAQs

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