Platform: Code4rena
Start Date: 13/12/2022
Pot Size: $36,500 USDC
Total HM: 5
Participants: 77
Period: 3 days
Judge: gzeon
Total Solo HM: 1
Id: 191
League: ETH
Rank: 62/77
Findings: 1
Award: $19.22
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Soosh
Also found by: 9svR6w, Apocalypto, Ch_301, HE1M, Koolex, SmartSek, Titi, Trust, Zarf, bin2chen, btk, carrotsmuggler, csanuragjain, dic0de, dipp, gz627, hansfriese, hihen, imare, immeas, indijanc, jadezti, kuldeep, ladboy233, maks, neumo, obront, rvierdiiev, sces60107, sk8erboy
19.2206 USDC - $19.22
Admin can turn rogue and steal the winner's NFT
Compromised admin can call lastResortTimelockOwnerClaimNFT to steal the winner's NFT.
function lastResortTimelockOwnerClaimNFT() external onlyOwner { // If recoverTimelock is not setup, or if not yet occurred if (settings.recoverTimelock > block.timestamp) { // Stop the withdraw revert RECOVERY_IS_NOT_YET_POSSIBLE(); } // Send event for indexing that the owner reclaimed the NFT emit OwnerReclaimedNFT(owner()); // Transfer token to the admin/owner. IERC721EnumerableUpgradeable(settings.token).transferFrom( address(this), owner(), settings.tokenId ); }
the NFT is transferred to owner(), not the winner. If the owner just do not want to give the winner's NFT and turn rogue, winner is rugged.
Manual Review
We recommend the project change the lastResortTimelockOwnerClaimNFT to:
/// @notice Optional last resort admin reclaim nft function /// @dev Only callable by the owner function lastResortTimelockOwnerClaimNFT() external onlyOwner { // If recoverTimelock is not setup, or if not yet occurred if (settings.recoverTimelock > block.timestamp) { // Stop the withdraw revert RECOVERY_IS_NOT_YET_POSSIBLE(); } // here address winner = IERC721EnumerableUpgradeable(settings.drawingToken).ownerOf( request.currentChosenTokenId ); // Send event for indexing that the owner reclaimed the NFT emit OwnerReclaimedNFT(winner); // Transfer token to the admin/owner. IERC721EnumerableUpgradeable(settings.token).safeTransferFrom( address(this), winner, settings.tokenId ); }
can use safeTransfer to make sure the receiver can receive NFT. If the safeTransfer revert, then transfer the NFT to owner.
#0 - c4-judge
2022-12-17T16:34:52Z
gzeon-c4 marked the issue as duplicate of #146
#1 - c4-judge
2023-01-23T16:53:19Z
gzeon-c4 marked the issue as satisfactory
#2 - c4-judge
2023-01-23T17:09:44Z
gzeon-c4 changed the severity to 3 (High Risk)