Premature Claim in Collection Shutdown Due to NFT Re-Listing
Summary
Bug Report: Premature Claim in Collection Shutdown Due to NFT Re-Listing
1. Bug Title:
Premature Claim Enabled by Relisted NFTs in SudoSwap Liquidation Pool
2. Why this could be triggered?
The current collectionLiquidationComplete() function solely verifies if the SudoSwap pool directly owns the NFTs. However, a user can buy an NFT from the SudoSwap liquidation pool and subsequently re-list it. This results in the pool no longer being the owner, misleading the function into wrongly concluding that all NFTs have been sold. Consequently, it prematurely enables claims.
3. PoC flow to trigger:
Initiate Collection Shutdown: Trigger the collection shutdown process, send NFTs to a SudoSwap pool for liquidation.
Partial Purchase: A user (User A) buys a subset of the NFTs in the SudoSwap pool.
Re-Listing: User A lists their recently purchased NFTs, on a platform outside the flayer ecosystem, at a potentially higher price.
False Completion Signal: The collectionLiquidationComplete() function incorrectly returns true because the SudoSwap pool no longer owns the relisted NFTs.
Premature Claims: Token holders, assuming liquidation is complete, invoke the claim() function and withdraw their proportional ETH prematurely, despite remaining unsold NFTs.
4. Impact:
Incorrect ETH Distribution: Users could claim a larger ETH share than entitled to if they claim before all NFTs are sold. The params.availableClaim wouldn't accurately reflect the full ETH proceeds from the liquidation if unsold NFTs remain.
Potential Losses: Users who purchased and relisted the NFTs risk potential losses if the relisted NFTs fail to sell at a higher price, leading to an overall reduction in the total ETH collected.
Flawed Protocol Logic: The bug compromises the intended security and accuracy of the collection shutdown mechanism. It defeats the purpose of equitable ETH distribution amongst token holders based on actual NFT sales proceeds.
5. Code Snippet:
function collectionLiquidationComplete(address _collection) public view returns (bool) {
CollectionShutdownParams memory params = _collectionParams[_collection];
uint sweeperPoolTokenIdsLength = params.sweeperPoolTokenIds.length;
// If we have no registered tokens, then there is nothing to check
if (sweeperPoolTokenIdsLength == 0) {
return true;
}
// Store our loop iteration variables
address sweeperPool = params.sweeperPool;
IERC721 collection = IERC721(_collection);
// Check that all token IDs have been bought from the pool
for (uint i; i < sweeperPoolTokenIdsLength; ++i) {
// BUG: Only checks for direct SudoSwap pool ownership,
//ignores the possibility of NFT re-listing
if (collection.ownerOf(params.sweeperPoolTokenIds[i]) == sweeperPool) {
return false;
}
}
return true;
}
Minato7namikazi
Invalid
Premature Claim in Collection Shutdown Due to NFT Re-Listing
Summary
Bug Report: Premature Claim in Collection Shutdown Due to NFT Re-Listing
1. Bug Title:
Premature Claim Enabled by Relisted NFTs in SudoSwap Liquidation Pool
2. Why this could be triggered?
The current
collectionLiquidationComplete()
function solely verifies if the SudoSwap pool directly owns the NFTs. However, a user can buy an NFT from the SudoSwap liquidation pool and subsequently re-list it. This results in the pool no longer being the owner, misleading the function into wrongly concluding that all NFTs have been sold. Consequently, it prematurely enables claims.3. PoC flow to trigger:
collectionLiquidationComplete()
function incorrectly returnstrue
because the SudoSwap pool no longer owns the relisted NFTs.claim()
function and withdraw their proportional ETH prematurely, despite remaining unsold NFTs.4. Impact:
params.availableClaim
wouldn't accurately reflect the full ETH proceeds from the liquidation if unsold NFTs remain.5. Code Snippet:
Root Cause
No response
Internal pre-conditions
No response
External pre-conditions
No response
Attack Path
No response
Impact
No response
PoC
No response
Mitigation
No response