Platform: Code4rena
Start Date: 04/11/2022
Pot Size: $42,500 USDC
Total HM: 9
Participants: 88
Period: 4 days
Judge: 0xean
Total Solo HM: 2
Id: 180
League: ETH
Rank: 77/88
Findings: 2
Award: $14.14
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: neko_nyaa
Also found by: 0x52, 0xSmartContract, 0xc0ffEE, Josiah, KingNFT, Lambda, R2, RaymondFam, Ruhum, TomJ, Trust, TwelveSec, __141345__, c7e7eff, cccz, cryptostellar5, fs0c, hansfriese, horsefacts, ladboy233, minhtrng, pashov, rvierdiiev, sashik_eth, tonisives, wagmi
8.5414 USDC - $8.54
The code contains logic to prevent the usage of fee-on-transfer tokens as the baseToken
. No such logic is present for the quoteToken
which can lead to faulty accounting and tokens getting stuck.
The function createAuction
checks if the baseToken
has fees-on-transfer and reverts if it does:
uint256 balanceAfterTransfer = ERC20(auctionParams.baseToken).balanceOf(address(this)); if (balanceAfterTransfer - balanceBeforeTransfer != auctionParams.totalBaseAmount) { revert UnexpectedBalanceChange(); }
This check is not present in the function bid
where the quoteToken
is transferred into the contract. During refund
, cancelAuction
or finalize
this can lead to reversions and tokens being locked, due to the contract holding less quoteToken
than the code assumes:
ebid.quoteAmount = quoteAmount; //assumes full quoteAmount will end up getting transferred to contract ... // no checks here however SafeTransferLib.safeTransferFrom(ERC20(a.params.quoteToken), msg.sender, address(this), quoteAmount);
Manual Review
Perform the same check for unexpected balance changes in bid
as is done in createAuction
, and also revert here if fee-on-transfer-tokens are not meant to be used.
#0 - c4-judge
2022-11-09T19:49:47Z
0xean marked the issue as duplicate
#1 - c4-judge
2022-12-06T00:22:19Z
0xean marked the issue as satisfactory
🌟 Selected for report: Trust
Also found by: 0x1f8b, 0xdapper, HE1M, KIntern_NA, Lambda, Picodes, RaymondFam, RedOneN, TomJ, V_B, __141345__, c7e7eff, chaduke, codexploder, corerouter, cryptonue, fs0c, gz627, hihen, joestakey, ktg, ladboy233, minhtrng, rvierdiiev, simon135, skyle, slowmoses, wagmi, yixxas
5.604 USDC - $5.60
The implementation for bidding has a DOS prevention mechanism, which can be abused to disable others from participating in auctions and being able to win the auction at the reserve price.
The bid
function contains the following logic:
if (bidIndex >= 1000) { revert InvalidState(); }
While the purpose of having this logic to avoid a DOS during finalize
is clear and reasonable, the drawback is that someone could create 1000 bids in an automated way to occupy all bid slots and be guaranteed to win the auction at the reserveQuotePerBase
auction. The exploiter could also cancel most of them right after creation to limit the amount of quoteTokens he needs to perform the attack.
A savvy auction creator would of course be able to monitor this behavior and decide not to finalize and re-do the auction, which would essentially turn into cat-mouse-game scenario, where the exploiter is disadvantaged in terms of gas costs. Depending on the specific network fees and the economical incentive of winning the auction, this can still be a practical issue.
Manual review
There is no easy fix that does not require an in-depth rework of the current implementation. An idea would be to enable partial reveals, with the requirement that the partial reveals cover all bids. This would however increase the complexity of necessary accounting and bookkeeping.
#0 - trust1995
2022-11-08T23:37:48Z
I believe this specific exploit is not an issue because buyer agreed to buy at this specific price, and seller can choose not to finalize if they are not satisfied with the bid array.
#1 - c4-judge
2022-11-09T15:37:06Z
0xean marked the issue as duplicate
#2 - c4-judge
2022-12-06T00:22:21Z
0xean marked the issue as satisfactory