Bid Beasts

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

Subsequent bids must be ≥5% higher, but tests allow invalid bids

Root + Impact

Description

  • Normal behavior: According to S_MIN_BID_INCREMENT_PERCENTAGE = 5, subsequent bids must be at least 5% higher than the previous bid.

  • Issue: Tests such as test_placeSubsequentBid_RefundsPrevious attempt a new bid that is not ≥5% higher, yet expect it to succeed. In reality, the contract correctly reverts with "Bid not high enough".

else {
requiredAmount = (previousBidAmount / 100) * (100 + S_MIN_BID_INCREMENT_PERCENTAGE);
@> require(msg.value >= requiredAmount, "Bid not high enough");
}

Risk

Likelihood:

  • This occurs whenever tests don’t align with the 5% increment logic.

Impact:

  • Misleading tests: Developers may misinterpret failing tests as contract bugs.

  • Reduced confidence: Inconsistent test expectations erode trust in the suite.


Proof of Concept

function testFail_SubsequentBidNotHighEnough() public {
// First bid of 0.01 ETH
vm.deal(BIDDER1, 0.01 ether);
vm.prank(BIDDER1);
market.placeBid{value: 0.01 ether}(TOKEN_ID);
// Second bid of 0.0104 ETH (not 5% higher)
vm.deal(BIDDER2, 0.0104 ether);
vm.prank(BIDDER2);
market.placeBid{value: 0.0104 ether}(TOKEN_ID);
// Reverts: "Bid not high enough"
}

Explanation:
The contract enforces the 5% increment rule correctly, but there is no test case for that.


Recommended Mitigation

Explanation:
Write a test for it.

Fix:

function test_fail_SubsequentBidNotHighEnough() public {
_mintNFT();
// Seller approves marketplace
vm.prank(SELLER);
nft.approve(address(market), TOKEN_ID);
// Seller lists the NFT
vm.prank(SELLER);
market.listNFT(TOKEN_ID, MIN_PRICE, 0);
// First bidder places a valid bid of 1 ETH
vm.deal(BIDDER_1, MIN_PRICE);
vm.prank(BIDDER_1);
market.placeBid{value: MIN_PRICE}(TOKEN_ID);
// Second bidder tries to bid less than 5% more (e.g., 1.04 ETH < 1.05 ETH)
uint256 invalidBid = MIN_PRICE + ((MIN_PRICE * 4) / 1000); // +0.4%
vm.deal(BIDDER_2, invalidBid);
vm.prank(BIDDER_2);
vm.expectRevert("Bid not high enough");
market.placeBid{value: invalidBid}(TOKEN_ID);
}

Use this formula in all tests for subsequent bids.

Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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