A potential Denial of Service (DoS) vulnerability exists in the MembershipFactory::upgradeTier
function, triggered by an arithmetic underflow in the MembershipERC1155::burn_
function. This issue occurs when a member of a sponsored DAO attempts to upgrade their membership tier, but the transaction fails due to an underflow in the calculation of MembershipERC1155::totalSupply
. This state can be achieved when there are very few users in the entire protocol.
The vulnerability arises from the MembershipERC1155::burn_
function, which contains the following code:
This highlited line of code in MembershipERC1155::burn_
attempts to decrement MembershipERC1155::totalSupply
based on the amount of NFTs to burn and the user's tier level. The issue occurs when the function tries to burn NFTs from a user who is a member in the sponsored DAO and wants to upgrade his tier via MembershipFactory::upgradeTier
, with very few users in the entire protocol. This action could fail and result in an arithmetic underflow issue.
Specifically, when the user joins a DAO, the corresponding NFT (amount 1) will be minted, as shown in the MembershipFactory::joinDAO
function below:
The MembershipERC1155::mint
function updates the MembershipERC1155::totalSupply
:
If the user joined the sponsored DAO, he might want to upgrade his tier, via MembershipFactory::upgradeTier
function. The function's logic will attempt to burn the user's lower tier NFTs (amount 2) and then mint an NFT for the next tier, thus upgrading the user's tier:
The function's logic depends heavily on the correct execution of MembershipERC1155::burn
and the calculation of MembershipERC1155::totalSupply
.
So what happens when the entire protocol has a very few users, and one of them who has just joined a newly created sponsored DAO, wants to upgrade his tier by calling the upgradeTier
function? This action could result in an underflow and cause the transaction to fail, as the MembershipERC1155::totalSupply
value could be less than the calculated amount for the burn, due to this line in the code [https://github.com/Cyfrin/2024-11-one-world/blob/main/contracts/dao/tokens/MembershipERC1155.sol#L74]. This issue could lead to a Denial of Service (DoS) scenario where the upgrade process fails for some users in a new sponsored DAOs attempting to upgrade their tiers.
The "OneWorld" protocol has just been launched and the first DAO (which is in your example a sponsored DAO) is created using MembershipFactory::createNewDAOMembership
. As there are no DAO members in the whole protocol, the MembershipERC1155::totalSupply
will initially be 0.
The first user wishes to join the newly created sponsored DAO using MembershipFactory::joinDAO
with a tier index of 1. One NTF will be minted for the user and the MembershipERC1155::totalSupply
will have a value of 32, since totalSupply += amount * 2 ** (6 - tokenId)
.
Shortly afterwards the same user decides to upgrade his tier using MembershipFactory::upgradeTier
. So he would have to burn 2 lower tier NFTs, but first the MembershipERC1155::totalSupply
would be updated, since totalSupply -= amount * 2 ** (6 - tokenId)
and the value of amount
is hardcoded to 2. In this particular case, totalSupply
would approach a negative value, since 2 * 2 ** (6 - 1) == 64
and 32 - 64 == -32
!!! As MembershipERC1155::totalSupply
is of type uint256
, it cannot hold negative values and the transaction will be rolled back, resulting in a DoS.
In order to upgrade, this member will have to wait until the protocol has enough users to join the DAOs.
For the test to be successful, the beforeEach
section of MembershipFactory.test.ts
in DAOConfig
should contain noOfTiers: 7
, daoType: DAOType.SPONSORED
and TierConfig
should have exactly 7 configurations, as shown in the example below:
After the adjustment in MembershipFactory.test.ts
is done, the following test can be added to MembershipFactory.test.ts
and executed using npx hardhat test test/MembershipFactory.test.ts --network localhost
(with running anvil):
The upgrade will revert as expected due to an arithmetic underflow, here is the log:
If an underflow occurs, it will cause the entire transaction to revert, preventing a member from upgrading his tier. This can be problematic in some scenarios where the protocol has a sponsored DAO and yet a very small total number of users. In this case, it may be possible to experience a DoS while attempting to upgrade a tier, as the calculation of totalSupply
in MembershipERC1155::burn_
could result in an arithmetic underflow and the entire tier upgrade mechanism could fail (see the "Attack Scenario" and "PoC" sections above). This could temporarily prevent legitimate upgrades in a sponsored DAO.
Manual review, Hardhat, VSCode
Consider updating the MembershipERC1155::burn_
function to include a check for underflows before modifying totalSupply
. This can be done by ensuring that the new value of totalSupply
does not go negative:
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.