code-423n4 / 2022-05-opensea-seaport-findings

1 stars 0 forks source link

Frontrunning Private Trades Vulnerability #99

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Lines of code

https://github.com/code-423n4/2022-05-opensea-seaport/blob/7c082637d9273deb42e551c74a578151cefd8448/contracts/lib/ConsiderationStructs.sol#L133-L152

Vulnerability details

Impact

The inability to create private trades in the Seaport contract would affect users significantly. Users will be forced to create public trades that run the risk of being frontrun.

Proof of Concept

Today, all trades are private (meant for specific offerer and fulfiller addresses and noone else can be a party to the trade). Platforms like NFTtrader, Sudoswap, etc. facilitate these private trades via their contract and users are used to such a structure.

Seaport has taken a different stance and is assuming all trades are public. The order hash is composed of order parameters and the nonce. Order parameters contains the offerer address but not the fulfiller address. This means that there is no way to enforce an offer to be only accepted by a specific fulfiller address (no way to do private trades).

Even the current Opensea interface facilitates private sales for a specific address ("Reserve For Specific Buyer"). So, Opensea users will expect similar private trades through Seaport.

While it may be argued that this is just a lack of the private trades feature in Seaport and hence not a bug. But because 100% of today's trades are private, users are not familiar with public trades. So, they will be forced to create public listings for private trades - which can then be frontrun.

Frontrunning can be countered by utilizing a private mempool (e.g. flashbots) but the majority of the Opensea user base is not educated on private mempools and so, this is practically not feasible.

Frontrunning can also be countered by utilizing a commit-reveal scheme on the zone. However, this will require every zone to have this functionality, and also require every private trade to be a restricted offer. This is also practically not feasible.

Since frontrunning cannot be countered in a practically feasible manner, the Opensea user base may suffer huge losses with their private trades being frontrun.

Tools Used

Visual Studio Code

Recommended Mitigation Steps

It is recommended to include a fulfiller address in the order parameters. If it is a zero address (for public trades), this address will not be checked. Otherwise the fulfiller address must match (for private trades).

0age commented 2 years ago

This is incorrect; to do a private sale the offerer just includes the intended sale recipient as a consideration item on the original order, then the fulfiller uses matchOrders and includes a second order offering their item and with no consideration (as their consideration is included in the original order)

HardlyDifficult commented 2 years ago

It appears there is a way to implement private sales. It should be possible to craft a solution using zones as well.