Normal behavior: sellers should only collect USDC proceeds after a real sale has occurred for their listing.
Issue: collectUsdcFromSelling allows collection whenever a listing is inactive. A listing becomes inactive after both buy() and cancelListing(), so canceled (unsold) listings can still withdraw listing.price - fees.
The listing lifecycle currently conflates two different terminal states under a single boolean:
sold listing: payout should be allowed
canceled listing: payout should not be allowed
Because both states map to isActive = false, the claim function cannot differentiate a valid settlement from a canceled listing. This lets an attacker reuse canceled listing data (listing.price) to pull USDC from the contract's shared balance, even when no sale occurred for that listing.
Likelihood:
Listing cancellation is a standard user flow and deterministically sets isActive = false.
Any later USDC funded by honest users can be stolen by calling the claim path on a canceled listing.
Impact:
Unauthorized transfer of USDC from protocol-held pooled balance.
Honest participants can be indirectly robbed because balances are commingled.
sellerA creates listing #1 and cancels it, which makes it inactive without a sale.
sellerB creates listing #2; another user buys it, adding USDC to contract balance.
sellerA calls collectUsdcFromSelling(1) on canceled listing #1.
The function accepts because it only checks !isActive.
sellerA receives payout for a listing that never sold, proving theft from pooled funds.
The fix enforces explicit settlement state:
isSold ensures only actually sold listings can be claimed.
claimed ensures payout happens once.
With these guards, canceled listings are permanently ineligible for sale-proceeds withdrawal. This removes the cross-listing fund-drain vector and aligns payout authorization with real sale completion.
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.
The contest is complete and the rewards are being distributed.