Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: low
Likelihood: high
Invalid

Previous Bidder Can Bypass "Already Highest Bidder" Restriction Using Buy-Now Price

BidBeastsNFTMarketPlace.sol - line 142

Description

  • In the normal behavior, the placeBid function should prevent the current highest bidder from placing another bid, whether it's a regular bid or a buy-now purchase.

  • The specific issue is that the check require(msg.sender != previousBidder, "Already highest bidder"); is placed after the buy-now logic block, allowing the current highest bidder to bypass this restriction by placing a bid equal to or greater than the buyNowPrice.

// Root cause in the codebase with @> marks to highlight the relevant section
function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ... existing code ...
// --- Buy Now Logic ---
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
// @> Previous bidder can execute buy-now and bypass the restriction
uint256 salePrice = listing.buyNowPrice;
uint256 overpay = msg.value - salePrice;
// ... buy-now execution ...
return;
}
// @> This check comes too late - previous bidder already executed buy-now above
require(msg.sender != previousBidder, "Already highest bidder");
// ... rest of function ...
}

Risk

Likelihood: High

  • This will occur whenever a previous bidder attempts to place a new bid using the buy-now price mechanism.

Impact: Low

  • This breaks the intended auction mechanics where the highest bidder should not be able to place additional bids.

Recommended Mitigation

Move the require(msg.sender != previousBidder, "Already highest bidder"); check to the beginning of the function, right after the seller check and before the buy-now logic. This ensures that the current highest bidder cannot place any additional bids, whether they're regular bids or buy-now purchases.

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(msg.sender != previousBidder, "Already highest bidder");
// auctionEnd == 0 => no bids yet => allowed
// auctionEnd > 0 and block.timestamp >= auctionEnd => auction ended => block
require(listing.auctionEnd == 0 || block.timestamp < listing.auctionEnd, "Auction ended");
// --- Buy Now Logic ---
if (listing.buyNowPrice > 0 && msg.value >= listing.buyNowPrice) {
// ... existing buy-now logic ...
return;
}
- require(msg.sender != previousBidder, "Already highest bidder");
// ... rest of function ...
}
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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