Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Inconsistent DAO Membership Tracking Caused by Unaccounted Token Burn and Mint Operations.

Summary

The updateDAOMembership function fails to account for recent burns and mints when updating tier configurations, leading to an inaccurate calculation of maxMembers When users burn tokens in one tier to mint tokens in another, these changes aren't reflected in the updateDAOMembership function, which copies outdated minted values and calculates an incorrect maximum membership

Vulnerability Details

The vulnerability lies in the handling of the minted values for each tier during the updateDAOMembership process:

lets see how this works:

  1. Dao minted only 1 tokenId_0 and 2 tokenId_1

  2. member wants to burn 2 tokenId_1 to get 1 tokenId_0

  3. he calls upgradeTier and burn 2 toeknId_1 and mint 1 tokenId_0

  4. updateDAOMembership is called EXTERNAL_CALLER to updated tierConfigs

  5. in loop this execute tierConfigs[i].minted = dao.tiers[i].minted; which has the old values because not updated.

  6. now wrong values will be stored in dao.tiers.push(tierConfigs[i]); maxMembers += tierConfigs[i].amount;

POC:

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);
}
function updateDAOMembership(string calldata ensName, TierConfig[] memory tierConfigs) external onlyRole(EXTERNAL_CALLER) returns(address) {
//...
uint256 maxMembers = 0;
// Preserve minted values and adjust the length of dao.tiers
for (uint256 i = 0; i < tierConfigs.length; i++) {
if (i < dao.tiers.length) {
@>>> // [0].minted is 1 but it should be 2 after upgradeTier and tokenId_0 is minted.
@>>> // [1].minted is 2 but it should be 0 after upgradeTier and tokenId_1 is burned.
@>>> // this will store wrong number of maxMembers.
@>>> tierConfigs[i].minted = dao.tiers[i].minted;
}
}
delete dao.tiers;
for (uint256 i = 0; i < tierConfigs.length; i++) {
@>>> // tiers are stored in array which will be stored and DAOs
@>>> // can call tiers function to see TierConfig which will be wrong.
@>>> dao.tiers.push(tierConfigs[i]);
@>>> maxMembers += tierConfigs[i].amount;
}
//...
}
// @notice Returns the tier configurations for a given membership NFT address
// @param membershipNftAddress The address of the Membership ERC1155 token
// @return An array of TierConfig
function tiers(address membershipNftAddress) external view returns(TierConfig[] memory) {
@>>> // this will return wrong tiers configurations of the given membership NFTs
@>>> return daos[membershipNftAddress].tiers;
}

Impact

the number of maxMembers will return wrong value any one who calls tiers function to see Tiers info he will get wrong tiers minted numbers which can effect the DAO who calls this to see how tiers information.

Recommendations

Update dao.tiers[i].minted value after calling upgradeTier

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.