When updating a DAO membership with the updateDAOMembership
function there is no checks made to make sure that the new tierConfigs[].amount
is not less than the already existing dao.tiers[].minted
. This will cause discrepencies in the contract while also breaking the invariants that the amount of minted tokens in a tier can not bypass the amount of tokens allowed to be minted and amount of maxMembers
allowed in a DAO cannot be less than the amount of members in the DAO.
The EXTERNAL_CALLER
role can update a dao with the updateDAOMembership
function.
As observed from this function, there are no checks done to make sure than the new tierConfigs[].amount
is greater than or equal to the already existing dao.tiers[].minted amount
.
Consider the scenario where in a DAO's configuration, in Tier 3, the maximum allowed amount to be minted is 4 and members have joined this tier 4 times. Now Tier 3 is 4 out of 4 minted. The EXTERNAL_CALLER
role now updates this DAO with the updateDAOMembership
function and changes the Tier 3's maximum allowed minted amount to 2. Now Tier 3 will be 4 out of 2 minted and breaking the invariant where amount of minted tokens is greater than the maximum allowed amount that is mintable in this tier.
Another invariant that breaks here is the amount of maxMembers
that can be in a DAO. This value is calculated by adding up the new tierConfigs[].amount
values. Not making sure that the new amounts are greater than or equal to the already existing amount of minted tokens will lead to the new maxMembers
value being less than the amount of members that already exist, leading to this invariant also breaking. maxMembers
value will store a value that is less than the amount of members in the DAO.
The issues that are caused here are:
Before the update, in order for new users to join Tier 3 they would have to wait for any user in Tier 3 to call the upgradeTier
function which would empty out 2 slots for new users to join. However, because the allowed amount is not validated to be greater than or equal to already existing amount , in order for new users to join this tier they will have to wait for two different upgradeTier
function calls.
maxMembers
state variable will store a value that is less than already existing number of members.
Maximum amount of tokens that can be minted in a tier will be less than the amount of tokens that are already minted.
1) Implement a new getter function in MembershipFactory.sol
to make tests easier.
2) Implement a mock WETH contract for testing inside the test folder.
3) Implement and run the following test to observe the vulnerability
Impact: Medium
Likelihood: Low, requires the EXTERNAL_CALLER
role to update the DAO with a new amount that is less than the existing minted amount.
Manual review, foundry
Implement a new check in the for loop in the updateDAOMembership
function to make sure that the new tierConfigs[].amount
is greater than or equal to the already existing dao.tiers[].minted
.
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.