-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A cunning user can always win the auction and claim the token being auctioned for free #1337
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-1323
satisfactory
satisfies C4 submission criteria; eligible for awards
Comments
c4-submissions
added
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
labels
Nov 12, 2023
141345 marked the issue as duplicate of #1904 |
141345 marked the issue as not a duplicate |
141345 marked the issue as duplicate of #1370 |
141345 marked the issue as duplicate of #962 |
alex-ppg marked the issue as not a duplicate |
alex-ppg marked the issue as duplicate of #1788 |
c4-judge
added
the
satisfactory
satisfies C4 submission criteria; eligible for awards
label
Dec 8, 2023
alex-ppg marked the issue as satisfactory |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-1323
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#L58
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L105
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L125
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L135
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L113
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L116
Vulnerability details
Impact
As described in the
Proof of Concept
section below, a cunning user is able to always win the auction and claim the auctioned token for free.Proof of Concept
The file
AuctionDemo.sol
contains the functions:participateToAuction
,claimAuction
,cancelBid
andcancelAllBids
:participateToAuction
function is intended to be used when the auction is OPENclaimAuction
function is intended to be used when the auction is CLOSEDcancelBid
function is intended to be used when the auction is OPENcancelAllBids
function is intended to be used when the auction is OPENHowever, based on the implementations of these functions, exactly at the moment
block.timestamp == minter.getAuctionEndTime(_tokenid)
, the auction is both OPEN and CLOSED at the same time. The snippets from these functions allowing an auction to be OPEN and CLOSED at the same time are given below:participateToAuction
function: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L58C59-L58C112claimAuction
function: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L105C17-L105C70cancelBid
function: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L125C17-L125C70cancelAllBids
function: https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L135C17-L135C70The root of the issue is that non-strict inequalities are used:
>=
and<=
instead of strict inequalities:>
and<
whenblock.timestamp
andminter.getAuctionEndTime(_tokenid)
are compared.The fact that at
block.timestamp == minter.getAuctionEndTime(_tokenid)
the auction is both OPEN and CLOSED can be exploited and the following scenario is possible:Alice calls the
participateToAuction
function and makes the highest bid up to the moment for the token being auctioned. The transaction becomes part of a block for whichblock.timestamp == minter.getAuctionEndTime(_tokenid)
istrue
.Alice calls the
claimAuction
function in a transaction that is part of a block for whichblock.timestamp == minter.getAuctionEndTime(_tokenid)
istrue
. By calling theclaimAuction
function, Alice wins the auction (she has the highest bid) and gets the token. Because the return value of the low-levelcall
function is not checked in the following 2 places:there is a possibility that the call wasn't successful, but there is no revert. In case these
call
function invocations fail, bidders and the original owner of the token being auctioned will not receiveETH
and someETH
amount will remain inside theauctionDemo
contract.cancelBid
function in a transaction that is part of a block for whichblock.timestamp == minter.getAuctionEndTime(_tokenid)
istrue
. As a result of thecancelBid
function invocation, Alice can claim theETH
amount from her winning bid back (this might happen if theauctionDemo
contract has enoughETH
, which can be possible if there are failingcall
function invocations in theclaimAuction
function beforehand, which is possible, since the return values of thecall
function invocations inclaimAuction
are not checked).To recap, following this strategy:
Alice always wins the token auction, because she makes the winning bid at the last possible moment (
block.timestamp == minter.getAuctionEndTime(_tokenid)
). Since the auction is both OPEN and CLOSED at that moment, she is able to claim the token being auctioned right after making her winning bid.Alice takes the
ETH
amount from her winning bid back by cancelling her winning bid at the momentblock.timestamp == minter.getAuctionEndTime(_tokenid)
, right after claiming the auctioned token.So, Alice managed to win the auction and get the auctioned token for free.
Tools Used
Manual review.
Recommended Mitigation Steps
To mitigate the possibility of a cunning user always winning the auction, we should make sure that in no moment in time is it possible the auction to be both OPEN and CLOSED. This can be achieved by modifying the
claimAuction
function in the way shown below:The essential change is on the line starting with
>>>
and ending with<<<
and the change consists of replacingblock.timestamp >= minter.getAuctionEndTime(_tokenid)
withblock.timestamp > minter.getAuctionEndTime(_tokenid)
. This way a cunning user cannot make the winning bid and win the auction in the same block. This fix also ensures that the auction winner cannot take his winning bid back, since thecancelBid
function cannot be successfully called after theclaimAuction
function, becausecancelBid
requires the auction to be OPEN andclaimAuction
requires the auction to be CLOSED and the fix ensures there is no moment in time when the auction is both OPEN and CLOSED. So, thecancelBid
function can be called successfully only before theclaimAuction
function.For completeness, I've also added checks for the success of the
ETH
transfer in the mitigated code snippet above, although that's something already known from the bot report. The lines of the checks added start with>>>>>
and end with<<<<<
.Assessed type
Timing
The text was updated successfully, but these errors were encountered: