Project

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

Unbounded Loop in ```Membership1155::burnBatchMultiple``` leading to gas exhaustion

Summary

The Membership1155::burnBatchMultiple burns all tokens of multiple users iterating over each element in the froms array without an upper bound. This leads to gas exhaustion if the array is very large, causing the transaction to fail and no burns can happen.

Link; https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/dao/tokens/MembershipERC1155.sol#L91-L103

Vulnerability Details

The for loop in the burnBatchMultiple function does not have an upper bound, it will attempt to process all the burns in a single transaction. If the from array has a large number of users, the gas required to execute the function may exceed the block gas limit, resulting in a failed transaction.

@> function burnBatchMultiple(address[] memory froms)
public
onlyRole(OWP_FACTORY_ROLE)
{
for(uint256 j = 0; j < froms.length; ++j){
for(uint256 i = 0; i < 7; ++i){
uint256 amount = balanceOf(froms[j], i);
if (amount > 0) {
burn_(froms[j], i, amount);
}
}
}
}

Impact

POC:

Set the project for using foundry:

  • Run: npm install --save-dev @nomicfoundation/hardhat-foundry

  • in the harhdat.config.ts file add this line: import "@nomicfoundation/hardhat-foundry";

  • run: npx hardhat init-foundry

  • in the test folder create a file named BurnButchMultipleOutOfGastTest.t.sol and copy and paste this into the file:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import {Test, console2} from "forge-std/src/Test.sol";
import {MembershipERC1155} from "../contracts/dao/tokens/MembershipERC1155.sol";
import {OWPERC20} from "../contracts/shared/TestERC20.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
contract BurnButchMultipleOutOfGastTest is Test {
OWPERC20 testERC20;
MembershipERC1155 membershipERC1155;
TransparentUpgradeableProxy membershipERC1155Proxy;
ProxyAdmin proxyAdmin;
address public creator = makeAddr("creator");
string public tokenURI = "https://example.com/{id}.json";
function setUp() public {
testERC20 = new OWPERC20("OWP", "OWP");
proxyAdmin = new ProxyAdmin(msg.sender);
membershipERC1155 = new MembershipERC1155();
membershipERC1155Proxy = new TransparentUpgradeableProxy(
address(membershipERC1155),
address(proxyAdmin),
abi.encodeWithSignature(
"initialize(string,string,string,address,address)",
"TestToken",
"TST",
tokenURI,
address(creator),
address(testERC20)
)
);
membershipERC1155 = MembershipERC1155(address(membershipERC1155Proxy));
}
function test_burnBatchMultipleGetOutOfGas() public {
address[] memory users = new address[]();
for (uint256 i = 1; i < users.length; i++) {
users[i] = vm.addr(i);
membershipERC1155.mint(users[i], 1, 100);
}
uint256 initialGas = gasleft();
membershipERC1155.burnBatchMultiple(users);
uint256 finalGas = gasleft();
uint256 gasUsed = initialGas - finalGas;
console2.log("gasUsed", gasUsed);
uint256 GAS_LIMIT = 30_000_000;
assert(gasUsed > GAS_LIMIT);
}
}
Logs;
Ran 1 test for test/BurnButchMultipleOutOfGastTest.t.sol:BurnButchMultipleOutOfGastTest
[PASS] test_burnBatchMultipleGetOutOfGas() (gas: 119855006)
Logs:
gasUsed 30003305
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 253.17ms (243.87ms CPU time)

The test shows that if the from array contains more than 2285 users, the function reverts and all the burns are reverted. No burn can happen inside the transaction. Considering that a DAO can have a large number of users (for example: the sponsored DAO can have a max number of users equal to 19825) is reasonable to consider that can be necessary to burn all tokens of a large number of users.

Tools Used

Manual review

Recommendations

Implement an upper limit to handle the burn of the token of a max number of users.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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