A buyer calls buy(listingId) to purchase an NFT at the listed price. The function reads listing.price from storage at execution time and transfers that amount from the buyer.
buy() accepts no maxPrice parameter. The seller can call updatePrice between the buyer's transaction submission and execution, inflating the price up to type(uint32).max (~4294 USDC). The buyer's transaction executes at the new price with no way to reject it. There is also no deadline parameter, so stale transactions in the mempool remain valid indefinitely.
Likelihood:
Every time a buyer submits a buy() transaction, the seller can front-run it with updatePrice to inflate the price. The buyer has no way to specify a maximum acceptable price.
Transactions without a deadline remain valid in the mempool indefinitely, giving the seller unlimited time to observe and front-run.
Impact:
The buyer pays up to ~4294 USDC (type(uint32).max) instead of the originally listed price. On a 10 USDC listing, this is a 429x overpayment.
Damage is bounded by the uint32 price type (~4294 USDC max) and the buyer's USDC approval. Buyers who approve exact amounts are protected by the ERC20 allowance, but buyers with large or max approvals are fully exposed.
A seller lists an NFT at 10 USDC. The buyer sees the listing, approves 10,000 USDC (a generous amount for multiple future purchases), and submits buy(). The seller front-runs with updatePrice(tokenId, type(uint32).max), inflating the price to ~4294 USDC. The buyer's buy() executes at the inflated price. The buyer pays 4294 USDC instead of 10 — a 429x overpayment — with no revert or warning.
Add maxPrice and deadline parameters to buy(). The buyer specifies the maximum price they accept and a timestamp after which the transaction expires. This prevents both price inflation front-runs and stale mempool transactions.
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.