Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: low
Valid

Failed Payout Credit Storage (funds may become effectively locked)

Root + Impact

Description

  • Normal behaviour: Outgoing ETH transfers to users (sellers, refunded bidders) should succeed, or there should be a reliable and user-friendly mechanism to recover funds.

  • Issue: When an external transfer fails, _payout it silently increments failedTransferCredits[recipient]. If recipients are contracts that cannot accept ETH (or forget to withdraw), funds may remain inaccessible indefinitely.

// Root cause in the codebase with @> marks to highlight the relevant section
function _payout(address recipient, uint256 amount) internal {
if (amount == 0) return;
(bool success, ) = payable(recipient).call{value: amount}("");
@> if (!success) {
@> failedTransferCredits[recipient] += amount;
}
}

Risk

Likelihood:

  • When recipient is a contract with a reverting fallback or deliberately rejects ETH transfers.

  • When recipients are unaware or forget to invoke withdrawAllFailedCredits, leaving credits unclaimed.

Impact:

  • Real ETH belonging to users becomes stuck in the contract or practically inaccessible, leading to financial loss and trust damage.

  • High-severity because user funds are affected.

Proof of Concept

// PoC sketch:
// 1) Deploy a recipient contract that reverts in receive()/fallback()
// 2) Cause a payout to that recipient (e.g., a refund or seller payout)
// 3) _payout attempts transfer, fails, failedTransferCredits[recipient] increases
// 4) Recipient cannot receive direct transfers and might not call withdrawAllFailedCredits (or withdraw could be restricted)

Recommended Mitigation

- if (!success) {
- failedTransferCredits[recipient] += amount;
- }
+ if (!success) {
+ // optionally emit event to notify recipient of credit
+ failedTransferCredits[recipient] += amount;
+ emit FailedPayoutCredited(recipient, amount);
+ }

Notes about mitigation:

Emitting an event improves discoverability so recipients and monitoring services can react.

Optionally providing a pull-based withdrawal path with clear UI instructions and event logs reduces the chance of funds being forgotten. The require(success) approach prevents silent credits but can block flows — choose based on user experience goals.

Updates

Lead Judging Commences

cryptoghost Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts Marketplace: Incorrect Event Emission

placeBid emits AuctionSettled even though the auction hasn’t ended, causing misleading event logs.

Support

FAQs

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

Give us feedback!