Bid Beasts

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

Premature Event Emission in Buy Now Logic in the `BidBeastsNFTMarketplace::placeBid()` function

Description

  • Events should accurately reflect when actions occur and contain correct parameters that match the actual transaction state.

  • The BidBeastsNFTMarketplace::placeBid() function incorrectly emits an AuctionSettled event with msg.value instead of the actual sale price during buy now purchases, and emits the event before the auction is actually settled.

require(msg.sender != previousBidder, "Already highest bidder");
@> emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);

Risk

Likelihood:

  • Occurs every time someone uses the buy now feature

  • Event listeners and analytics will receive incorrect information

Impact:

  • Misleading event logs for external systems and indexers

  • Incorrect price data being recorded in events

Proof of Concept

function test_HIGH_PrematureEventEmissionBuyNow() public {
uint256 tokenId = _mintAndListNFT(ALICE, MIN_PRICE, BUY_NOW_PRICE);
// First bidder places a regular bid
vm.prank(BOB);
market.placeBid{value: MIN_PRICE + 0.1 ether}(tokenId);
// Second bidder triggers buy now
vm.prank(CHARLIE);
// VULNERABILITY: AuctionSettled event is emitted with wrong parameters during buy now
vm.expectEmit(true, true, false, false);
emit BidBeastsNFTMarket.AuctionSettled(
tokenId,
CHARLIE,
ALICE,
BUY_NOW_PRICE // Event shows BUY_NOW_PRICE but actual msg.value might be higher
);
market.placeBid{value: BUY_NOW_PRICE}(tokenId);
// The event should be emitted by _executeSale, not during placeBid
// This creates confusion about when the auction actually settled
}

Recommended Mitigation

// --- Buy Now Logic ---
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
uint256 salePrice = listing.buyNowPrice;
uint256 overpay = msg.value - salePrice;
// EFFECT: set winner bid to exact sale price (keep consistent)
bids[tokenId] = Bid(msg.sender, salePrice);
listing.listed = false;
if (previousBidder != address(0)) {
_payout(previousBidder, previousBidAmount);
}
- require(msg.sender != previousBidder, "Already highest bidder");
- emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);
// NOTE: using internal finalize to do transfer/payouts. _executeSale will assume bids[tokenId] is the final winner.
_executeSale(tokenId);
// Refund overpay (if any) to buyer
if (overpay > 0) {
_payout(msg.sender, overpay);
}
return;
}
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month 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.