Description
Due to how the internal tracking of bids is implemented with a ContractAddress to amount map only the last bid amount is stored for a Bidder using the same ContractAddress. This means if:
Bidder1
bids the following 3 bids:
1
10
30
Then Bidder2
bids the following amount; then the auction finishes and so Bidder2 is the winner:
31
The total in the contract is 31 + 30 + 10 + 1 = 72
The NFT / Auction owner withdraws 31
leaving 41
.
Bidder1
attempts to withdraw their failed bids, expecting to get 41
tokens refunded, but only receives 30
tokens which is their most recent bid amount.
NOTE: The example above is a contrived example used to simplify the explanation of the issue; typically Bidder1 would not bid against themselves.
The issue lies with the fact the map shown below only tracks the last bid amount not the total of the bids for the Bidder/ ContractAddress.
Impact
Bidder's funds are potentially trapped in the contract and they cannot legitimately withdraw them.
Proof of Concept
Within the bid function this line(in red) only writes the current bid (amount
) into the bid_values
map where we need to get the current amount that has been bid previously and add that to the new bid amount.
Something like the following is indicative of a potential solution (this code is untested and should be considered purely as an example of a possible implementation)
The bid function contains the following code (in red), where amount is the current amount being bid in the transaction.
Recommended mitigation
Improve bid tracking and accounting logic such that all user bids are tracked and can be withdrawn.
References
N/A
Tools Used
Manual Review
In the `bid` function the bid values are stored using `self.bid_values.entry(sender).write(amount)` directly, but this overwrites any previous bids made by the same bidder. Therefore if a participant makes 2 or more bids, the participant can then withdraw only the last value of the last bid. That is incorrect, the protocol should save all bids and a participant should withdraw the value of the all unsuccessful bids.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.