Root Cause
In list(), listings are stored using _tokenId as the mapping key, but listingsCounter is incremented and emitted as the listingId in the event. These two values are never in sync.
Impact: Any off-chain system or frontend using the emitted listingId to look up a listing will retrieve an empty or incorrect struct.
When a user lists an NFT, the listing is stored at s_listings[_tokenId]. However the event emits listingsCounter as the listingId. These two values diverge as soon as the first NFT listed does not have a tokenId matching the current listingsCounter.
Likelihood: High
This occurs every time an NFT with a tokenId that does not match the current listingsCounter is listed
Any user who mints multiple NFTs and lists them out of order will trigger this immediately
Impact: Medium
Off-chain systems, frontends, and indexers relying on the emitted listingId to look up listings will retrieve empty structs
buyers relying on the emitted listingId to call buy() will pass the wrong key and the transaction will revert with ListingNotActive
// PoC: We prove the emitted listingId is out of sync with the actual mapping key
// by minting 5 NFTs and only listing token ID 5, showing the event emits listingId=1
// while the real listing is stored at s_listings[5] thus making s_listings[1] empty
// remove emitting listingsCounter which is out of sync with the mapping key and we replace it with
// emit tokenId so off-chain systems can correctly look up the listing
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.
The contest is complete and the rewards are being distributed.