Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: low
Invalid

Auction Sniping Vulnerability in `placeBid` Function

Summary

The placeBid function in NFTLiquidator.sol does not extend the auction end time when a new bid is placed. This allows for auction sniping, where a bidder can be placed in the last block of the auction end time and have no competition, undermining the integrity of the auction.

Vulnerability Details

In the placeBid function, the auction's auctionEndTime remains unchanged when a new bid is placed:

function placeBid(uint256 tokenId) external payable {
TokenData storage data = tokenData[tokenId];
if (block.timestamp >= data.auctionEndTime) revert AuctionHasEnded();
uint256 minBidAmount = data.highestBid + (data.highestBid * minBidIncreasePercentage / 100);
if (msg.value <= minBidAmount) revert BidTooLow(minBidAmount);
if (data.highestBidder != address(0)) {
payable(data.highestBidder).transfer(data.highestBid);
}
data.highestBid = msg.value;
data.highestBidder = msg.sender;
emit BidPlaced(tokenId, msg.sender, msg.value);
}

Since the auction time does not get extended, a participant can wait until the last moment to bid, preventing other participants from placing counter-bids. This effectively enables a form of auction sniping, where the last bidder can win with minimal competition.

Impact

  • Unfair Auction Process: Bidders can game the system by placing a bid at the last block, preventing fair competition.

  • Suboptimal Revenue for Sellers: The auction may not reach its true market price since competing bidders are unable to respond.

Tools Used

Manual review

Recommended Mitigation

To prevent auction sniping, introduce an auction time extension mechanism where the auction end time is extended by a small duration (e.g., 5–10 minutes) when a bid is placed near the closing time.

Modify placeBid to extend the auction when a new bid is placed within a predefined threshold (e.g., 5 minutes before the end):

function placeBid(uint256 tokenId) external payable {
TokenData storage data = tokenData[tokenId];
if (block.timestamp >= data.auctionEndTime) revert AuctionHasEnded();
uint256 minBidAmount = data.highestBid + (data.highestBid * minBidIncreasePercentage / 100);
if (msg.value <= minBidAmount) revert BidTooLow(minBidAmount);
if (data.highestBidder != address(0)) {
payable(data.highestBidder).transfer(data.highestBid);
}
data.highestBid = msg.value;
data.highestBidder = msg.sender;
+ // Extend auction if bid is placed in the last 5 minutes
+ if (block.timestamp + 5 minutes > data.auctionEndTime) {
+ data.auctionEndTime = block.timestamp + 5 minutes;
+ }
emit BidPlaced(tokenId, msg.sender, msg.value);
}

This ensures that last block bids extend the auction, allowing fair competition while preventing infinite extensions since each bid must be higher by a fixed percentage.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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

Give us feedback!