Bid Beasts

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

`BidBeastsNFTMarket:placeBid` Function: Incorrect Calculation Logic Causes Bid Amount to Round Down

BidBeastsNFTMarket:placeBid Function: Incorrect Calculation Logic Causes Bid Amount to Round Down

Description

  • Under normal circumstances, when the placeBid function handles a buyer placing a bid in an auction, starting from the second bid, each subsequent bid amount must be greater than the previous bid.

  • However, due to an error in the bid calculation logic, subsequent bid amounts may be rounded down, meaning the next bid might not actually reach the intended 5% increase.

  • The relevant code in BidBeastsNFTMarketPlace.sol is as follows:

function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ... Original code
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);
}
}
// ... Original code
}

Risk

Likelihood:

  • This calculation logic is triggered every time a buyer places a subsequent bid.
    Impact:

  • While there is no direct fund loss, it could allow the next minimum bid to be slightly lower than the true 5% increase, which violates the protocol's intended design.

Proof of Concept

  • The original code performs division first, followed by multiplication, which is a clear source of precision loss.

Recommended Mitigation

function placeBid(uint256 tokenId) external payable isListed(tokenId) {
// ... Original code
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);
+ uint256 minIncrement = (previousBidAmount * S_MIN_BID_INCREMENT_PERCENTAGE) / 100;
+ if (minIncrement == 0) minIncrement = 1; // Ensure at least a 1 wei increase
+ requiredAmount = previousBidAmount + minIncrement;
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);
}
}
// ... Original code
}
Updates

Lead Judging Commences

cryptoghost Lead Judge 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts Marketplace: Integer Division Precision Loss

Integer division in requiredAmount truncates fractions, allowing bids slightly lower than intended.

Support

FAQs

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

Give us feedback!