Claiming refunds on ongoing auctions make NFTs free#
High Risk
In Funds.sol there is claimDutchRefund
function that is used to claim the refund from a refundable dutch auction.
Anyone who bought an NFT on this kind of auction, can execute this function any time. This can lead to people getting free NFTs.
Example#
- User A creates a canvas and sets it up for a refundable dutch. Starting price is 10 ETH, ending price is 5 ETH and total quantity is 10.
- User B buys one NFT at the beginning of the auction and pays 10 ETH.
- He can then immediately execute the
claimDutchRefund
function. - His refund will be calculated like this
purchaseTracker.spend - (purchaseTracker.quantity * (ds.canvasSystem[canvasId].dutchEndPrice))
=10 ETH - (1 * 0)
= 10 ETH
So the user just bought an NFT for free. The dutchEndPrice
is 0, because it gets set only when the amount of NFTs sold reaches the total quantity (in the above case 10).
This example is not taking into account the protocol fee, which can be 0 - 30 %.
Recommendation#
Since the reason for above exploit is that auction has not ended, meaning ds.canvasSystem[canvasId].dutchEndPrice
is not set, you can simply check if it is zero and revert (if(ds.canvasSystem[canvasId].dutchEndPrice == 0) revert
). Notice that you are only allowing claiming of funds after amount of NFTs sold reaches the total quantity (that is when ds.canvasSystem[canvasId].dutchEndPrice
is set). This raises another issue that is described in Never ending refundable dutch. It includes a solution that takes into account both issues, and it would be recommended to use it.