Starknet Auction

First Flight #26
Beginner FriendlyNFT
100 EXP
View results
Submission Details
Severity: high
Invalid

The NFT owner can withdraw not only the highest bid but also the amount from unsuccessful bids.

Summary

If the NFT owner places a bid on the protocol, their amount will be added to the bid values map.

self.bid_values.entry(sender).write(amount);

Because of this, during the withdrawal process, the NFT owner can transfer not only the highest bid but also the all unsuccessful bid amounts from other clients to their account.

Vulnerability Details

According to the protocol description, the NFT owner can transfer the highest bid. However, it is also possible for them to transfer the amounts from other clients' bids.

fn withdraw(ref self: ContractState) {
assert(self.started.read(), 'Auction is not started');
assert(self.ended.read(), 'Auction is not ended');
let caller = get_caller_address();
let sender = get_contract_address();
let erc20_dispatcher = IERC20Dispatcher { contract_address: self.erc20_token.read() };
let amount = self.bid_values.entry(caller).read();
let amount_owner = self.highest_bid.read();
// @audit here nft owner can transfer highest_bid
if caller == self.nft_owner.read() {
self.highest_bid.write(0);
self.bid_values.entry(sender).write(0)
erc20_dispatcher.transfer_from(sender, caller, amount_owner.into());
}
// @audit here nft owner can transfer founds from other clients
if amount > 0 {
let sender = get_contract_address();
erc20_dispatcher.transfer_from(sender, caller, amount.into());
}
self.emit(Withdraw {amount: amount, caller: caller});
}

Impact

The NFT owner can 'steal' funds from other clients.

Tools Used

manula review

Recommendations

Please modify the `withdraw` function:

fn withdraw(ref self: ContractState) {
assert(self.started.read(), 'Auction is not started');
assert(self.ended.read(), 'Auction is not ended');
let caller = get_caller_address();
let sender = get_contract_address();
let erc20_dispatcher = IERC20Dispatcher { contract_address: self.erc20_token.read() };
let amount_owner = self.highest_bid.read();
if caller == self.nft_owner.read() {
self.highest_bid.write(0);
// @audit add this line
self.bid_values.entry(caller).write(0)
erc20_dispatcher.transfer_from(sender, caller, amount_owner.into());
}
let amount = self.bid_values.entry(caller).read();
if amount > 0 {
let sender = get_contract_address();
// @audit and this to prevent reetrancy attack
self.bid_values.entry(caller).write(0)
erc20_dispatcher.transfer_from(sender, caller, amount.into());
}
self.emit(Withdraw {amount: amount, caller: caller});
}
Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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