Forgeries contest - ladboy233's results

A protocol for on-chain games with NFT prizes on Ethereum.

General Information

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

Forgeries

Findings Distribution

Researcher Performance

Rank: 62/77

Findings: 1

Award: $19.22

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

19.2206 USDC - $19.22

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
duplicate-146

External Links

Lines of code

https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L315

Vulnerability details

Impact

Admin can turn rogue and steal the winner's NFT

Proof of Concept

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.

Tools Used

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)

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter