The MartenitsaEvent
contract currently from MartenitsaToken
, which unnecessarily exposes token management functionalities. This leads to shared state variables that can result in synchronization and access control issues across the codebase. Such an inheritance structure contradicts the principle of separation of concerns between event management and token management.
MartenitsaEvent
is supposed to contain event management functionalities, which is a completely separate concern from the NFT token management and producer management functionalities provided by MartenitsaToken
.
However, MartenitsaEvent
extends MartenitsaToken
via inheritance, inappropriately merging two disparate concerns. This inheritance structure gives MartenitsaEvent
unnecessary access to the internal mechanisms (e.g. NFT minting method) and state variables (e.g. producer lists) of MartenitsaToken
.
This setup causes several problems, probably the biggest of which is that both contracts maintain separate and uncoordinated internal states regarding which addresses are recognized as producers. The test below demonstrates one such state inconcistency between the 2 contacts (one contract recognizes an address as producer, the other not).
State Confusion: both contracts will maintain separate and uncoordinated internal states regarding which addresses are recognized as producers. I.e. addresses denoted as producers by MartenitsaToken
will not be recognized as producers by MartenitsaEvent
and vice versa.
Access Control Issues: state confusion causes access control issues, e.g.
-- Addresses recognized as producers by MartenitsaToken
are able to join an event via MartenitsaEvent::joinEvent
, even though as producers they are not supposed to. This is because MartenitsaEvent::joinEvent
only checks its own internal state regarding producer lists:
-- Addresses recognized as producers by MartenitsaEvent
(during the duration of an event) are able to collect rewards via MartentisaMartkerplace::collectRewards
even during an event, although they are not supposed to. This is because MartentisaMartkerplace::collectRewards
checks only MartenitsaToken
's internal state regarding producer lists:
-- Addresses recognized as producers by MartenitsaEvent
(during the duration of an event) are not able to create Martinetsa NFTs via MartinetsaToken::createMartinetsa
, only via MartinetsaEvent::createMartinetsa
which creates further state inconsistencies and accounting issues.
Function Exposure: MartenitsaEvent
gains access to NFT-specific functions that are irrelevant to its primary role of managing events. This not only adds unnecessary complexity to MartenitsaEvent
but also increases the attack surface of the codebase.
Manual review, Foundry.
MartenitsaEvent
should not inherit from MartenitsaToken
. Instead, it should contain an instance of MartenitsaToken
to allow explicit and controlled use of its functionalities. This change will limit MartenitsaEvent
to necessary interactions with MartenitsaToken
and prevent inadvertent exposure of token management features.
Consider the following modifications as a rough starting point for a fix. Note that the bug at hand is severe and fixing it requires rethinking the protocol design, thorough testing, and preferably another round of audit.
Note that a better, more elegant and simpler fix might be the following:
remove the inheritance
do not manipulate the state variables of MartenitsaMarketplace
to grant producer privilages to event participants for the duration of an event, but instead:
-- completely separate participant and producer statuses, and use only the participants
array and _participants
mapping for participants (and producer state variables only for real producers set by MartenitsaMarketplace
),
-- in all 5 contracts, whereever an action is gated for producers or non-producers, add a similar gate to the participants by referencing the particpants state variable of MartenitsaEvent
. (For this to work, importing MartenitsaEvent
will be needed in all affected contracts.)
This solution completely separates the handling of producers from participants. As such, it has the additional benefit that whenever an event ends, and the producer-like privilages of participants have to be revoked, it is enough to simply reset the participants
array and _participants
mapping.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.