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);
}
* @notice Tests a more extreme fairness issue: the seller ends the auction just as the extension begins.
*/
function test_auctionFairnessIssue_SellerEndsAuctionImmediatelyAfterExtension() public {
_mintNFT();
_listNFT();
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE}(TOKEN_ID);
uint256 auctionEndTime = market.getListing(TOKEN_ID).auctionEnd;
console.log("Auction extended to:", auctionEndTime);
console.log("Extension duration:", market.S_AUCTION_EXTENSION_DURATION());
vm.prank(SELLER);
market.takeHighestBid(TOKEN_ID);
assertEq(nft.ownerOf(TOKEN_ID), BIDDER_1, "NFT transferred to first bidder");
assertFalse(market.getListing(TOKEN_ID).listed, "Auction ended immediately");
console.log("CRITICAL ISSUE: Seller can end auction immediately after extension starts");
console.log("This makes the extension mechanism completely unfair to other bidders");
}
* @notice Tests the situation where a bidder is about to bid but the seller ends the auction first.
*/
function test_auctionFairnessIssue_BidderPreparingBidButSellerEndsFirst() public {
_mintNFT();
_listNFT();
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE}(TOKEN_ID);
uint256 auctionEndTime = market.getListing(TOKEN_ID).auctionEnd;
uint256 almostEndTime = auctionEndTime - 1;
vm.warp(almostEndTime);
console.log("BIDDER_2 preparing to bid with 1 second left");
console.log("Current time:", block.timestamp);
console.log("Auction ends at:", auctionEndTime);
vm.prank(SELLER);
market.takeHighestBid(TOKEN_ID);
assertEq(nft.ownerOf(TOKEN_ID), BIDDER_1, "First bidder got NFT despite BIDDER_2 wanting to bid");
console.log("UNFAIR: Seller ended auction before BIDDER_2 could place their bid");
console.log("BIDDER_2 had valid time remaining but was denied the opportunity");
}
//Sellers can only close the deal after the auction ends
function takeHighestBid(uint256 tokenId)
external
isListed(tokenId)
isSeller(tokenId, msg.sender)
{
Listing storage listing = listings[tokenId];
Bid storage bid = bids[tokenId];
require(bid.amount >= listing.minPrice, "Highest bid is below min price");
require(listing.auctionEnd > 0, "Auction not started");
require(block.timestamp >= listing.auctionEnd, "Auction not ended yet");
_executeSale(tokenId);
}