Bid Beasts

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

Seller Can Prematurely End Auction With `takeHighestBid`, Breaking the 3-Day Duration Rule

Seller Can Prematurely End Auction With takeHighestBid, Breaking the 3-Day Duration Rule

Description

  • Normally, according to the documentation, each auction must last exactly 3 days, after which anyone can finalize it by calling endAuction(tokenId). This ensures transparency and fairness, giving all bidders the same timeframe.

  • However, the function takeHighestBid allows the seller to end the auction early, even before the 3-day period has passed. This behavior directly contradicts the documented protocol rules and breaks the expected auction flow.

function takeHighestBid(uint256 tokenId)
external
isListed(tokenId)
isSeller(tokenId, msg.sender)
{
Bid storage bid = bids[tokenId];
require(bid.amount >= listings[tokenId].minPrice, "Highest bid is below min price");
@> _executeSale(tokenId); // prematurely finalizes the auction
}

Risk

Likelihood:

  • Occurs whenever a seller decides to finalize the auction before the 3-day period.

  • More likely in cases where the seller believes the current bid is high enough and wants to lock it in.

Impact:

  • Breaks fairness by preventing other bidders from participating within the expected 3-day window.

  • Undermines trust in the marketplace, as the contract behavior does not match the documented rules.

Proof of Concept

  1. Seller lists an NFT for auction.

  2. A bidder places a bid, expecting 3 full days for competition.

  3. Seller immediately calls takeHighestBid(tokenId).

  4. Auction ends early, NFT is transferred, and the bidding process is prematurely cut off.

function test_sellerCanPrematurelyEndAuction() public {
uint256 buyNowPrice = 1 ether;
uint256 firstBid = 0.5 ether;
// seller lists an NFT for auction
vm.prank(OWNER);
uint256 tokenId = nft.mint(SELLER);
vm.startPrank(SELLER);
nft.approve(address(market), tokenId);
market.listNFT(tokenId, 0.3 ether, buyNowPrice);
vm.stopPrank();
// A bidder places a normal bid
vm.prank(BIDDER_1);
market.placeBid{value: firstBid}(tokenId);
// Seller immediately ends the auction with takeHighestBid
vm.prank(SELLER);
market.takeHighestBid(tokenId);
// Verify: NFT is already transferred to highest bidder before 3 days
assertEq(nft.ownerOf(tokenId), BIDDER_1);
}

Recommended Mitigation

Remove the takeHighestBid function entirely to ensure auctions always follow the fixed 3-day rule as per documentation.

- function takeHighestBid(uint256 tokenId) external isListed(tokenId) isSeller(tokenId, msg.sender) {
- Bid storage bid = bids[tokenId];
- require(bid.amount >= listings[tokenId].minPrice, "Highest bid is below min price");
- _executeSale(tokenId);
- }
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts Marketplace: Improper Documentation

Documentation for BidBeasts Marketplace is incomplete or inaccurate, potentially leading to misconfigurations or security misunderstandings.

Support

FAQs

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