Bid Beasts

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

Incorrect event emission

Root + Impact

Description

  • The AuctionSettled event should be only called when an auction has concluded to show that the NFT has been paid to the winner and payment released

  • The agreement incorrectly sends AuctionSettled on each usual placement of a bid before the close of the auction so event logs will show multiple fake settlement events per auction


function placeBid(uint256 tokenId) external payable isListed(tokenId) {
Listing storage listing = listings[tokenId];
address previousBidder = bids[tokenId].bidder;
uint256 previousBidAmount = bids[tokenId].amount;
require(listing.seller != msg.sender, "Seller cannot bid");
require(listing.auctionEnd == 0 || block.timestamp < listing.auctionEnd, "Auction ended");
// --- Buy Now Logic ---
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
// ... buy now logic ...
return;
}
require(msg.sender != previousBidder, "Already highest bidder");
emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value); // @> WRONG - auction not settled yet!
// --- Regular Bidding Logic ---
// ... rest of bidding logic ...
}

}

Risk

Likelihood:

  • Literally every single regular bid triggers this incorrect event emission

  • All auctions with multiple bids will have multiple false AuctionSettled events

Impact:

  • Off chain indexers and monitoring systems receive false auction completion info

  • Analytics dashboards show incorrect auction completion metrics

Proof of Concept

function testIncorrectAuctionSettledEvents() public {
address seller = address(0x1);
address bidder1 = address(0x2);
address bidder2 = address(0x3);
// Setup NFT and listing
vm.prank(owner);
nft.mint(seller, 1);
vm.startPrank(seller);
nft.approve(address(marketplace), 1);
marketplace.listNFT(1, 1 ether, 0);
vm.stopPrank();
// First bid
vm.deal(bidder1, 1.1 ether);
vm.expectEmit(true, true, true, true);
emit AuctionSettled(1, bidder1, seller, 1.1 ether);
vm.prank(bidder1);
marketplace.placeBid{value: 1.1 ether}(1);
// Second bid
vm.deal(bidder2, 1.2 ether);
vm.expectEmit(true, true, true, true);
emit AuctionSettled(1, bidder2, seller, 1.2 ether);
vm.prank(bidder2);
marketplace.placeBid{value: 1.2 ether}(1);
(, , , uint256 auctionEnd, bool listed) = marketplace.listings(1);
assert(listed == true);
assert(block.timestamp < auctionEnd);
// Wait for actual settlement
vm.warp(auctionEnd + 1);
vm.expectEmit(true, true, true, true);
emit AuctionSettled(1, bidder2, seller, 1.2 ether);
marketplace.settleAuction(1);
}

Recommended Mitigation

function placeBid(uint256 tokenId) external payable isListed(tokenId) {
Listing storage listing = listings[tokenId];
address previousBidder = bids[tokenId].bidder;
uint256 previousBidAmount = bids[tokenId].amount;
require(listing.seller != msg.sender, "Seller cannot bid");
require(listing.auctionEnd == 0 || block.timestamp < listing.auctionEnd, "Auction ended");
// --- Buy Now Logic ---
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
// ... buy now logic remains the same ...
return;
}
require(msg.sender != previousBidder, "Already highest bidder");
- emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);
// --- Regular Bidding Logic ---
// ... rest of function ...
emit BidPlaced(tokenId, msg.sender, msg.value); // Already exists at line end
}
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!