Bid Beasts

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

Misleading Event Data

Description

The contract creates an event AuctionSettled when an NFT is sold in an auction. However the contract will mistakenly create this event evertime a bid is placed, regardless if it actually leads to a sell or not.

function placeBid(uint256 tokenId) external payable isListed(tokenId) {
...
// --- 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");
// This event should not be called because the auction is still ongoing
emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value); <@
// --- Regular Bidding Logic ---
uint256 requiredAmount;
if (previousBidAmount == 0) {
requiredAmount = listing.minPrice;
require(msg.value > requiredAmount, "First bid must be > min price");
listing.auctionEnd = block.timestamp + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
} else {
requiredAmount = (previousBidAmount / 100) * (100 + S_MIN_BID_INCREMENT_PERCENTAGE);
require(msg.value >= requiredAmount, "Bid not high enough");
uint256 timeLeft = 0;
if (listing.auctionEnd > block.timestamp) {
timeLeft = listing.auctionEnd - block.timestamp;
}
if (timeLeft < S_AUCTION_EXTENSION_DURATION) {
listing.auctionEnd = listing.auctionEnd + S_AUCTION_EXTENSION_DURATION;
emit AuctionExtended(tokenId, listing.auctionEnd);
}
}
...
emit BidPlaced(tokenId, msg.sender, msg.value);
}

Risk

Likelihood:

  • This will happen with everybid that does not cause a revert.

Impact:

  • This will negatively affect any off chain apps that require accurate information related to auction event handling. This will make it difficult to determine when the auction actually has been settled.

Proof of Concept

If a user makes a valid minimum price bid the acctionSettled event emitted.

function test_auction_event_error() public {
_mintNFT();
_listNFT();
uint256 FIRST_BID = MIN_PRICE + 1;
vm.expectEmit(false, false, false, true, address(market));
emit AuctionSettled(TOKEN_ID, BIDDER_1, SELLER, FIRST_BID); // This event should only be emitted during the sell of a NFT
vm.prank(BIDDER_1);
market.placeBid{value: FIRST_BID}(TOKEN_ID);
}

Recommended Mitigation

The fix would be to remove the event emit from placeBid function and only have it in the _executeSale function.

require(msg.sender != previousBidder, "Already highest bidder");
- emit AuctionSettled(tokenId, msg.sender, listing.seller, msg.value);
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.