One of the invariants of the protocol is that users can only claim HealthToken if they own three different MartenisaTokens, but due to the lack of access control in MartenitsaToken::updateCountMartenitsaTokensOwner any user can call the function to increase their token counter, without actually owning any token, and then execute MartenitsaMarketplace::collectReward to get free rewards.
Rewards can be minted for free by following the next steps:
User calls three time MartenitsaToken::updateCountMartenitsaTokensOwner
Now that the user's token counter is equal to 3, he calls MartenitsaMarketplace::collectReward
Now the user owns 1 HealthToken
To verify the exploit, paste the following test in MartenitsaToken.t.sol:
Invariant of the protocol broken, HealthTokens can be minted for free
Manual review, Foundry
I recommend refactoring the external updateCountMartenitsaTokensOwner function into two new functions as such:
an external updateCountMartenitsaTokensOwner function to act as an exclusive entry point for MartenitsaMarketplace, because this is the only external contract that needs access to MartenitsaToken::countMartenitsaTokensOwner
an internal _updateCountMartenitsaTokensOwner function to be called in the context of MartenitsaToken when a new token is minted in MartenitsaToken::createMartenitsa
Check the following example on how to update MartenitsaToken:
Update MartenitsaToken::createMartenitsa:
Create MartenitsaToken::updateCountMartenitsaTokensOwner:
Update MartenitsaToken::updateCountMartenitsaTokensOwner:
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.