The winner of the raffle may be a smart contract which doesn't handle NFTs, thus leaving the NFT irretrievably lost instead of being awarded to an address which can handle NFTs.
Additionally, the NFT should be in the VRFNFTRandomDraw contract at the time of the claiming. There is no need to use transferFrom in winnerClaimNFT or lastResortTimelockOwnerClaimNFT - safeTransfer / transfer is enough to transfer it out of the contract.
Proof of Concept
Deploy a standard contract with no ERC721 support, send one of the drawingToken NFTs to it.
Deploy a raffle using makeNewDraw in VRFNFTRandomDrawFactory, using the drawingToken as the NFT collection for the raffle.
Let's say the contract is selected as winner in startDraw and calls winnerClaimNFT.
The NFT gets transferred to the contract without checking if the contract is a ERC721Receiver, rendering the NFT lost.
Tools Used
VS Code, Forge
Recommended Mitigation Steps
Use safeTransfer instead of transferFrom in winnerClaimNFT.
Lines of code
https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L295
Vulnerability details
Impact
The winner of the raffle may be a smart contract which doesn't handle NFTs, thus leaving the NFT irretrievably lost instead of being awarded to an address which can handle NFTs. Additionally, the NFT should be in the
VRFNFTRandomDraw
contract at the time of the claiming. There is no need to usetransferFrom
inwinnerClaimNFT
orlastResortTimelockOwnerClaimNFT
-safeTransfer
/transfer
is enough to transfer it out of the contract.Proof of Concept
Deploy a standard contract with no ERC721 support, send one of the
drawingToken
NFTs to it. Deploy a raffle usingmakeNewDraw
inVRFNFTRandomDrawFactory
, using thedrawingToken
as the NFT collection for the raffle. Let's say the contract is selected as winner instartDraw
and callswinnerClaimNFT
. The NFT gets transferred to the contract without checking if the contract is aERC721Receiver
, rendering the NFT lost.Tools Used
VS Code, Forge
Recommended Mitigation Steps
Use
safeTransfer
instead oftransferFrom
inwinnerClaimNFT
.