auctionDemo::claimAuction
refunds all bidders in one call and can be DOS if one call consumes all available gas
#1357
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-734
edited-by-warden
satisfactory
satisfies C4 submission criteria; eligible for awards
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L116
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L110
Vulnerability details
Impact
As explained in the solidity documentation, unlike
transfer
orsend
,call
forwards all gas. An attacker, can set himself up as a bidder then forces the call to consume all available gas which will permanently DOS the functionauctionDemo::claimAuction
.The impact is high, as the winner cannot claim the NFT plus non-winning bidders can lose their funds because they will not be able to get a refund. All the auctions are impacted.
Proof of Concept
The following code line transfers all gas to the subsequent logic.
function
auctionDemo::claimAuction
:If one call is set up such as the
fallback
orreceive
function of the bidder's address consumes all gas, the functionclaimAuction
will permanently revert.The winner cannot claim the NFT. The other bidders cannot get a refund because the cancel functions assume that
minter.getAuctionEndTime(_tokenid)
has not yet been passed.POC
You can add this test to the file nextGen.t.sol of our foundry setup in gist C4 nextGen foundry setup. And execute it with the command forge test --mt testClaimAlwaysReverts -vvvv
Note that the test testClaimAlwaysReverts() never ends if run in foundry directly as unit testing does not consider the gas limit. But in a simulated chain or other web framework (Remix for example), this test should revert as expected because out of gas error.
Tools Used
Manual review + foundry
Recommended Mitigation Steps
auctionDemo::claimAuction
function as this creates weaknesses. Instead, allow each user (pull over push pattern) to withdraw his funds back (except for the winner). Also, allow bidders (except winner) to withdraw their funds at any time from the cancel functions.function
auctionDemo::claimAuction
:function
auctionDemo::cancelBid
:- require(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
function
auctionDemo::cancelAllBids
:- require(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
Assessed type
DoS
The text was updated successfully, but these errors were encountered: