The issue is that there's no check preventing a sold asset from being relisted. This could lead to the following attack scenario:
Asset is listed (status = 1)
Asset is purchased (status = 2)
Asset is relisted (status = 1)
Asset could be purchased again
This violates the intended state machine where an asset should not be transferable after being sold.
The contract fails to enforce proper state transitions for assets. Once an asset is sold, it can be relisted and sold again due to missing validation checks.
This is dangerous for the protocol because:
Assets can transition between states in unintended ways, breaking the core invariant that assets should follow Unlisted -> Listed -> Sold progression.
The same asset can be purchased multiple times since there's no permanent "Sold" state.
Multiple sales of the same asset would create artificial supply and potentially drain funds from buyers who purchase already-sold assets.
The ability to resell already sold assets breaks the fundamental NFT ownership guarantees that users expect.
The core issue stems from missing state transition validations, allowing assets to be recycled through the system multiple times when they should be permanently marked as sold.
The vulnerability connects directly to Swan's core asset management system, affecting:
Asset listing (list()
)
Asset purchases (purchase()
)
Asset relisting (relist()
)
State management (AssetStatus
)
This creates a circular path where assets can infinitely cycle through states that should be terminal.
PoC
Assets can be sold multiple times
Buyers can lose funds by purchasing already-sold assets
Market manipulation through artificial supply
Token transfers can occur for the same asset multiple times
Manual Review
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.