Event is called at wrong time
Description
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
uint256 salePrice = listing.buyNowPrice;
uint256 overpay = msg.value - salePrice;
bids[tokenId] = Bid(msg.sender, salePrice);
listing.listed = false;
if (previousBidder != address(0)) {
_payout(previousBidder, previousBidAmount);
}
_executeSale(tokenId);
if (overpay > 0) {
_payout(msg.sender, overpay);
}
return;
}
require(msg.sender != previousBidder, "Already highest bidder");
@> emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);
Risk
Likelihood:
-
The AuctionSettled event emits during every regular bid placement, occurring 100% of the time for non-buyNow bids
-
External systems and users receive false "auction ended" notifications on every single bid, creating consistent misinformation
Impact:
-
BuyNow settlements are invisible to external systems
-
Regular bids falsely appear as settlements
-
Buyers: Confused about auction statesProof of Concept
Proof Of Code
Scenario1: Buy Now Logic
1. User pays buyNowPrice (5 ETH)
2. _executeSale() transfers NFT to buyer
3. Auction is ACTUALLY settled
4. NO AuctionSettled event emitted
5. External systems don't know auction ended
Scenario2: Regular Bid
1. User places normal bid (1 ETH)
2. emit AuctionSettled() → "Auction ended!" //While it's still on
3. But auction continues accepting more bids
4. Time gets extended
5. External systems see impossible state
Recommended Mitigation
Delete `AuctionSettled` emitted at it's actaul location
// --- 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);
}
// 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;
}
require(msg.sender != previousBidder, "Already highest bidder");
- emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);