Normal behavior: A withdrawal function for failed outgoing payments should let an address reclaim only their own credited ETH, clear the recorded credit before performing an external transfer, and follow the checks-effects-interactions pattern so funds cannot be stolen or reentered.
Specific issue: The contract’s withdrawAllFailedCredits(address _receiver) reads the credit for the caller-specified _receiver but clears failedTransferCredits[msg.sender] and sends the read amount to msg.sender. This allows any caller to request someone else’s credited balance and have it paid to themselves, while the victim’s credit remains unchanged.
Likelihood:
The marketplace issues refunds and payouts to bidders/sellers, and some recipients are smart contracts that revert on receive; failed transfers are recorded frequently for refunds and overpay returns this creates failedTransferCredits entries for many addresses that an attacker can target.
The vulnerable withdraw function requires only gas and a single transaction.
Impact:
Attackers can steal the full amount of any failedTransferCredits entry for any victim address, with minimal gas cost.
Because the victim’s mapping entry is not cleared, the same credit can be stolen repeatedly or by multiple attackers, causing repeated loss until the bug is fixed resulting in potentially catastrophic fund loss and reputational damage.
Replace the vulnerable function with a caller-only withdrawal that clears the correct mapping key before doing the external transfer. Optionally add nonReentrant and an event for auditing. The diff below replaces the vulnerable function and suggests adding an event.
withdrawAllFailedCredits allows any user to withdraw another account’s failed transfer credits due to improper use of msg.sender instead of _receiver for balance reset and transfer.
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.