Summary
MembershipFactory::updateDAOMembership allows to change the existing dao's tier but there is no check between the past minted and new amount.
Vulnerability Details
function updateDAOMembership(string calldata ensName,TierConfig[] memory tierConfigs) external onlyRole(EXTERNAL_CALLER) returns (address) {
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
tierConfigs[i].minted = dao.tiers[i].minted;
}
}
delete dao.tiers;
for (uint256 i = 0; i < tierConfigs.length; i++) {
dao.tiers.push(tierConfigs[i]);
maxMembers += tierConfigs[i].amount;
}
_;
}
The minted value is preserved and will be used for the updated dao membership. Since there is no validation between the minted value and the new amount, there is a probability where the preserved minted value exceed the new amount for spesific tier.
Impact
Preserved minted value exceed the new amount
Tools Used
Manual Review
Recommendations
function updateDAOMembership(string calldata ensName,TierConfig[] memory tierConfigs) external onlyRole(EXTERNAL_CALLER) returns (address) {
// Preserve minted values and adjust the length of dao.tiers
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
tierConfigs[i].minted = dao.tiers[i].minted;
}
}
// Reset and update the tiers array
delete dao.tiers;
for (uint256 i = 0; i < tierConfigs.length; i++) {
dao.tiers.push(tierConfigs[i]);
+ if(tierConfigs[i].minted > tierConfigs[i].amount) tierConfigs[i].amount = tierConfigs[i].minted;
maxMembers += tierConfigs[i].amount;
}
_;
}