NFT Dealers

First Flight #58
Beginner FriendlyFoundry
100 EXP
Submission Details
Impact: high
Likelihood: high

H-3: Reentrancy in `cancelListing()` — USDC Transferred Before State Reset

Author Revealed upon completion

Description:

In cancelListing(), usdc.safeTransfer is called while collateralForMinting[listing.tokenId] still holds the collateral amount. An attacker with a malicious USDC token (or in a scenario where USDC supports transfer hooks) can re-enter cancelListing() and withdraw the collateral multiple times.

function cancelListing(uint256 _listingId) external {
...
s_listings[_listingId].isActive = false; // ← isActive updated
activeListingsCounter--;
usdc.safeTransfer(listing.seller, collateralForMinting[listing.tokenId]); // ← external call
collateralForMinting[listing.tokenId] = 0; // ← but collateral not cleared yet
...
}

Impact: A seller can recover their collateral multiple times, draining USDC from the contract.

Recommended Mitigation:

function cancelListing(uint256 _listingId) external {
Listing memory listing = s_listings[_listingId];
if (!listing.isActive) revert ListingNotActive(_listingId);
require(listing.seller == msg.sender, "Only seller can cancel listing");
// Effects first
s_listings[_listingId].isActive = false;
activeListingsCounter--;
uint256 collateral = collateralForMinting[listing.tokenId];
collateralForMinting[listing.tokenId] = 0;
// Interactions last
usdc.safeTransfer(listing.seller, collateral);
emit NFT_Dealers_ListingCanceled(_listingId);
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!