# CollectionBatchBuyOperator.sol: tokenIds array is not shortened properly which makes execute function revert when not all NFTs are purchased successfully

CollectionBatchBuyOperator's assembly to shorten tokenIds writes to wrong memory slot, so partial NFT purchase failures revert the whole execute instead of skipping.

- Payout: Contest reward
- Severity: medium
- Program: PartyDAO
- Credited: HollaDieWaldfee
- Disclosed: 2023-06-23
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-04-party-findings/issues/4
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-party%3AM-11
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** Solidity operator contract (CollectionBatchBuyOperator.execute)
**Root cause:** Assembly `mstore(mload(ex), tokensBought)` writes to the address stored in the first word of the execution-data struct rather than to the tokenIds array length slot, so the array is never shortened.
**Steps:**
1. Call `execute` with execution data where one of the `calls` fails (e.g. numOfTokens=3 but only 2 succeed).
2. Failed buy is skipped via `if (!success) continue;`, leaving a zero entry at end of `tokenIds`.
3. Assembly `mstore(mload(ex), tokensBought)` fails to update `tokenIds` length.
4. Transfer loop iterates full `tokenIds` and attempts `safeTransferFrom` of `tokenId=0`, reverting the whole proposal execution.
5. Fix: `mstore(tokenIds, tokensBought)`; adjust test `numOfTokens` to 3 to expose the bug.
**How found:** Code review of the assembly block shortening tokenIds; noticed `mload(ex)` dereferences the struct's first word instead of the array pointer, and confirmed via a modified Foundry test that the array length is not updated.
**Insight:** When auditing inline assembly that mutates dynamic array lengths, verify the mstore target is the array's own length slot (the pointer itself), not a value loaded from a struct field; also distrust passing tests—check whether test inputs actually exercise the failure path.
