Platform: Code4rena
Start Date: 08/11/2022
Pot Size: $60,500 USDC
Total HM: 6
Participants: 72
Period: 5 days
Judge: Picodes
Total Solo HM: 2
Id: 178
League: ETH
Rank: 1/72
Findings: 2
Award: $10,871.41
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: cccz
10835.0653 USDC - $10,835.07
When a user fulfills an order using SeaportProxy, fees are charged in the _handleFees function based on orders.price.
function _handleFees( BasicOrder[] calldata orders, uint256 feeBp, address feeRecipient ) private { address lastOrderCurrency; uint256 fee; uint256 ordersLength = orders.length; for (uint256 i; i < ordersLength; ) { address currency = orders[i].currency; uint256 orderFee = (orders[i].price * feeBp) / 10000;
According to the Seaport documentation, Seaport allows partial fulfillment of orders, which results in too much fee being charged when an order is partially filled https://docs.opensea.io/v2.0/reference/seaport-overview#partial-fills
Consider feeBp == 2% The order on Seaport has a fill status of 0/100 and each item is worth 1 eth. User A fulfills the order using LooksRareAggregator.execute and sends 102 ETH, where order.price == 100 ETH. Since the other user fulfilled the order before User A, when User A fulfills the order, the order status is 99/100 Eventually User A buys an item for 1 ETH but pays a fee of 2 ETH.
None
Consider charging fees based on the user's actual filled price
#0 - c4-sponsor
2022-11-24T17:56:18Z
0xhiroshi marked the issue as sponsor confirmed
#1 - 0xhiroshi
2022-11-24T17:56:22Z
We are dropping fees completely.
#2 - c4-judge
2022-12-11T12:47:28Z
Picodes marked the issue as satisfactory
🌟 Selected for report: RaymondFam
Also found by: 0x1f8b, 0x52, 0xSmartContract, 0xc0ffEE, 0xhacksmithh, 8olidity, Awesome, BClabs, Bnke0x0, Chom, Deivitto, Hashlock, IllIllI, Josiah, KingNFT, Nyx, R2, ReyAdmirado, Rolezn, SamGMK, Sathish9098, SinceJuly, V_B, Vadis, Waze, a12jmx, adriro, ajtra, aphak5010, bearonbike, bin, brgltd, carlitox477, carrotsmuggler, cccz, ch0bu, chaduke, datapunk, delfin454000, erictee, fatherOfBlocks, fs0c, horsefacts, jayphbee, ktg, ladboy233, pashov, perseverancesuccess, rbserver, ret2basic, tnevler, zaskoh
36.3434 USDC - $36.34
In the current implementation, LooksRareProxy only supports orders where the currency is ETH, but LooksRareProxy does not check that the currency is ETH, which may mess up the order execution. Consider user A to execute two orders using LooksRareProxy and SeaportProxy respectively, the order currency of LooksRareProxy is WETH and the price is 10 WETH, and the currency of SeaportProxy is ETH and the price is 80 ETH. When these two orders are executed, the correct result should be that LooksRareProxy's order fails due to incorrect currency and SeaportProxy's order succeeds. In actual execution, LooksRareProxy will use 10 ETH and execute successfully, while SeaportProxy's order fails because there are only 70 ETH left.
None
Check in LooksRareProxy.execute that currency is ETH
#0 - c4-sponsor
2022-11-24T16:36:36Z
0xhiroshi marked the issue as sponsor acknowledged
#1 - 0xhiroshi
2022-11-24T16:39:25Z
We will force LooksRare orders to be ETH instead of WETH in the frontend and we will not make any changes. Technically all LooksRare's listing currency are WETH so we don't have an easy way to differentiate the two on-chain.
#2 - Picodes
2022-12-11T13:15:59Z
The issue described by the finding is that WETH is in fact not handled by LooksRareProxy
although one could think from the order.currency
and the function name that it is. But a user sending WETH
will not lose its funds, and in the scenario you are describing - which is unlikely and conditional on a user mistake - the user was willing to fill the 10 WETH so no real harm is done.
Therefore there is no significant impact, so downgrading to QA because it could potentially be interesting to use WETH before ETH for LooksRare orders
#3 - c4-judge
2022-12-11T13:16:23Z
Picodes changed the severity to QA (Quality Assurance)
#4 - c4-judge
2022-12-11T13:16:42Z
Picodes marked the issue as grade-b