Foundation contest - 0xliumin's results

Building the new creative economy

General Information

Platform: Code4rena

Start Date: 24/02/2022

Pot Size: $75,000 USDC

Total HM: 21

Participants: 28

Period: 7 days

Judge: alcueca

Total Solo HM: 15

Id: 94

League: ETH

Foundation

Findings Distribution

Researcher Performance

Rank: 5/28

Findings: 2

Award: $4,653.83

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 0xliumin

Also found by: leastwood

Labels

bug
3 (High Risk)
sponsor confirmed

Awards

3652.1324 USDC - $3,652.13

External Links

Lines of code

https://github.com/code-423n4/2022-02-foundation/blob/4d8c8931baffae31c7506872bf1100e1598f2754/contracts/mixins/NFTMarketReserveAuction.sol#L325-L349 https://github.com/code-423n4/2022-02-foundation/blob/4d8c8931baffae31c7506872bf1100e1598f2754/contracts/mixins/NFTMarketReserveAuction.sol#L596-L599

Vulnerability details

Impact

NFT owner can permanently lock funds of bidders.

Proof of concept

Alice (the attacker) calls createReserveAuction, and creates one like normal. let this be auction id 1.

Alice calls createReserveAuction again, before any user has placed a bid (this is easy to guarantee with a deployed attacker contract). We'd expect that Alice wouldn't be able to create another auction, but she can, because _transferToEscrow doesn't revert if there's an existing auction. let this be Auction id 2.

Since nftContractToTokenIdToAuctionId[nftContract][tokenId] will contain auction id 2, all bidders will see that auction as the one to bid on (unless they inspect contract events or data manually).

Alice can now cancel auction id 1, then cancel auction id 2, locking up the funds of the last bidder on auction id 2 forever.

Mitigation

Prevent NFT owners from creating multiple auctions

#0 - HardlyDifficult

2022-02-28T20:03:43Z

This is a great find!

The impact of this bug is:

  • Bidder's funds are stuck in escrow in an unrecoverable way without an upgrade, and even with an upgrade it would have been non-trivial to offer a migration path to recover the funds (but it would have been possible to recover correctly).
  • It allows sellers to stop the clock and/or back out of an auction. Normally once a bid is received we do not allow the seller to cancel the auction. With this bug, they could have created a new auction and then cancel that in order to back out of the deal entirely. This violates trust with collectors.

We have fixed this problem by adding the following code to createReserveAuction:

    // This check must be after _transferToEscrow in case auto-settle was required
    if (nftContractToTokenIdToAuctionId[nftContract][tokenId] != 0) {
      revert NFTMarketReserveAuction_Already_Listed(nftContractToTokenIdToAuctionId[nftContract][tokenId]);
    }

Findings Information

Awards

1001.7004 USDC - $1,001.70

Labels

bug
QA (Quality Assurance)

External Links

QA Report

Overall I would recommend rethinking the architecture here. Some of the abstract contracts are leaky abstractions and have many cross dependencies.

Just an idea, have one contract that serves as a vault for the NFTs and manages all information about escrow for buy price / auction. That way there isn't so much state that you have to manage between all the different contracts and there's one contract that manages whether a given NFT is in escrow.

Low

Use safeTransferFrom / safeTransfer for ERC721

It's best practice to use this functions so NFTs don't get transferred to contracts that aren't aware of the protocol. Make sure you account for reentrancy though.

Large unchecked blocks

All the large unchecked blocks can potentially cause unexpected overflow issues in arithmetic. Make sure very unchecked block targets a very specific block of code (as opposed to large for loop blocks).

Non-critical

Incorrect comments in role mixins

These should be revokeRole, not grantRole https://github.com/code-423n4/2022-02-foundation/blob/4d8c8931baffae31c7506872bf1100e1598f2754/contracts/mixins/roles/AdminRole.sol#L35

https://github.com/code-423n4/2022-02-foundation/blob/4d8c8931baffae31c7506872bf1100e1598f2754/contracts/mixins/roles/OperatorRole.sol#L26

#0 - HardlyDifficult

2022-02-28T20:13:38Z

Thanks for the feedback!

  • Architecture: Another user suggested something very similar. It is very tempting to go that route, it does seem like it would clean up the code and offer a clear separation of responsibilities. However it may prevent us for using efficient slot packing and would be a very significant change to make shortly before our launch.
  • Use safeTransferFrom: This is a common recommendation but it does increase exposure to potential reentrancy issues. We do use nonReentrant for many calls, but we'd still like to limit external calls where possible just in case the modifier was missed in one of our flows. I'm not currently aware of a good use case which would require this -- but it is certainly something we are considering adding in the future.
  • Large unchecked blocks: We have comments around the usage of unchecked throughout the code. If there are any which are unsafe or not documented, we should look into those closer. In general, the reason for the large unchecked blocks is usually due to limitations with Solidity. For instance, in order to uncheck the ++i portion of a for loop, we need to wrap the entire loop as unchecked since Solidity does not yet have a way of scoping the unchecked section in-line. Once that capability is added, we will clean up the code to make unchecked blocks more targeted and easier to reason about.
  • Incorrect comments: This file is listed as out of scope -- however you are correct! This was a copy paste error in the comments and we have corrected them.

#1 - alcueca

2022-03-17T09:19:44Z

Unadjusted score: 55 (inclidung 30 points for the extensive architecture recommendations).

#2 - alcueca

2022-03-17T10:01:15Z

Extra 5 points from #24

#3 - alcueca

2022-03-18T11:07:06Z

Extra 5 points from #22.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter