Summary
The MemberShipFactory::upgradeTier function mints on fromTierIndex - 1 instead of fromTierIndex + 1.
Vulnerability Details
The MemberShipFactory::upgradeTier function allows users to upgrade their tier withing a sponsored DAO.
File: contracts/dao/MembershipFactory.sol#L155-L161
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.");
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}
The second require statement suggests that the user upgrades to the tier just higher to the given tier. However, the mint function is called on the tier just lower the given tier, which lead to the user upgrading the wrong tier.
Impact
The user is upgrading the wrong tier.
Tools Used
Manual review.
Recommendations
File: contracts/dao/MembershipFactory.sol#L155-L161
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.");
IMembershipERC1155(daoMembershipAddress).burn(_msgSender(), fromTierIndex, 2);
-- IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex - 1, 1);
++ IMembershipERC1155(daoMembershipAddress).mint(_msgSender(), fromTierIndex + 1, 1);
emit UserJoinedDAO(_msgSender(), daoMembershipAddress, fromTierIndex - 1);
}