Asset lister can prevent Swan contract from receiving their asset when trying to purchase()
When a user calls Swan.list(), a new ERC721 token is deployed and 1 token is minted for the lister (which is ERC721 token's owner as well). The constructor automatically approves _operator address (which is Swan contract) to transfer that token from the lister when it is going to be purchased.
However, the lister can disapprove the Swan contract just after token deployment by calling this function from ERC721 asset.
This way, when an authorized operator calls BuyerAgent.purchase(), the function will revert if any of the assets to be purchased got the approval revoked. This happens because BuyerAgent.purchase() loops all the decoded assets from BuyerAgent.oracleResult() and calls Swan.purchase() for each of them; Swan.purchase() tries to transferFrom the asset from the lister as it expects to be approved for so, but if approval is revoked as explained, then Swan.purchase() reverts.
If at least one of the assets that BuyerAgent intends to purchase gets the approval for Swan contract revoked, BuyerAgent will not be able to purchase any assets, leading to a DoS, as each of them is purchased individually with a loop. Even if the lister needs to transferRoyalties() to list an asset, the caused damage is much higher than its cost.
Manual review, Remix, ERC721 standard
The best idea to mitigate this issue is to modify SwanAsset so that lister can do nothing but wait until it is bought. Take into account that liste could revoke approval, send the token to another address, approve another address and transferFrom() the token from that address...
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.