Summary
Missing tier capacity validation in tier upgrades.
Vulnerability Details
The upgradeTier function allows members to upgrade to higher tiers without checking if the target tier has available capacity. While the joinDAO function enforces tier capacity limits, the upgrade function bypasses these checks entirely.
Each tier has a defined capacity:
struct TierConfig {uint256 amount;
And the joinDAO function enforces capacity:
require(daos[daoMembershipAddress].tiers[tierIndex].amount >
daos[daoMembershipAddress].tiers[tierIndex].minted,
"Tier full.");
https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L142
However, the upgradeTier function lacks this validation.
Impact
Tiers can exceed their designed capacity limits.
https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/MembershipFactory.sol#L155
Tools Used
Manual review
Recommendations
Add capacity check for target tier:
function upgradeTier(address daoMembershipAddress, uint256 fromTierIndex) external {
require(daos[daoMembershipAddress].daoType == DAOType.SPONSORED, "Upgrade not allowed.");
require(daos[daoMembershipAddress].noOfTiers >= fromTierIndex + 1, "No higher tier available.");
require(daos[daoMembershipAddress].tiers[fromTierIndex - 1].amount >
daos[daoMembershipAddress].tiers[fromTierIndex - 1].minted,
"Target tier is full");
daos[daoMembershipAddress].tiers[fromTierIndex].minted -= 1;
daos[daoMembershipAddress].tiers[fromTierIndex - 1].minted += 1;
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 1);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
}