Starknet Auction

First Flight #26
Beginner FriendlyNFT
100 EXP
View results
Submission Details
Severity: medium
Valid

NFT remains locked in contract when there are no bidders

Summary

The StarknetAuction contract does not properly handle the scenario when no bids are placed during the auction. As a result, if an auction ends with no valid bids, the NFT is not transferred back to the original owner, leading to it being locked within the contract indefinitely. This flaw could prevent the original owner from reclaiming the NFT, effectively causing a permanent asset loss.

Vulnerability Details

In the end() function of the StarknetAuction contract, the following logic is used to determine how to finalize the auction:

fn end(ref self: ContractState) {
let time = get_block_timestamp();
let caller = get_caller_address();
let erc721_dispatcher = IERC721Dispatcher { contract_address: self.erc721_token.read() };
let sender = get_contract_address();
assert(caller == self.nft_owner.read(), 'Not the nft owner');
assert(self.started.read(), 'Auction is not started');
assert(time >= self.bidding_end.read(), 'Auction is not yet ended');
assert(!self.ended.read(), 'Auction end is already called');
@> assert(self.starting_price.read() < self.highest_bid.read(), 'No bids');
self.ended.write(true);
self.emit(End {highest_bid: self.highest_bid.read(), highest_bidder: self.highest_bidder.read()});
erc721_dispatcher.transfer_from(sender, self.highest_bidder.read(), self.nft_id.read().into());
}

The line assert(self.starting_price.read() < self.highest_bid.read(), 'No bids'); is intended to prevent the auction from ending without a valid bid. However, this also means that if no bids are placed, the end() function will revert, leaving the NFT permanently locked in the contract, with no way for the original owner to reclaim it.

Proof of Concept

The following test case, included in the provided test library, demonstrates that the contract was designed to panic if there were no bids placed, resulting in the NFT being stuck in the contract:

#[test]
#[should_panic(expected: 'No bids')]
fn test_call_end_no_bids() {
let (auction_dispatcher, auction_contract, _, _) = deploy_auction_contract();
// The owner calls start function.
auction_dispatcher.start(86400, 10);
let time = get_block_timestamp();
start_cheat_block_timestamp(auction_contract, time + 86401);
auction_dispatcher.end();
stop_cheat_block_timestamp(auction_contract);
}

This test shows that if no bids are placed, attempting to end the auction will cause a panic with the message 'No bids'. As a result, the NFT remains in the auction contract, inaccessible to the original owner. This behavior was likely a design oversight, mistakenly leaving the NFT locked.

Impact

The NFT can become locked inside the contract if no bids are placed, resulting in:

  • Loss of Asset Ownership: The original owner permanently loses access to the NFT, as there is no function available to reclaim it.

  • Incomplete Auction Lifecycle: The auction cannot be properly finalized, leaving the contract in an undesirable state.

There are numerous possible reasons for why there would be no bidders at the auction. One of them could be that the owner initialized the auciton with too high of a starting_price_ _by mistake (eg. 1000 instead of 100 ether). Since there is no way to edit it, no one will ever bid if that price is way too high.

Tools Used

Manual review, Starknet Foundry

Recommendations

Update the end() Function Logic to allow the initial owner of the nft to be able to claim it whenever the bid has ended and there were no bidders

Updates

Lead Judging Commences

bube Lead Judge 8 months ago
Submission Judgement Published
Validated
Assigned finding tags:

The NFT will be locked if there are no bids

If there are no placed bids in the auction, the `end` function will always revert. The owner can not receive back the nft ant it will be locked in the contract.

Support

FAQs

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