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: 10/77
Findings: 3
Award: $481.10
🌟 Selected for report: 1
🚀 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
The contest readme states "This contract should prevent the owner from iterrupting the contest until the timelock unlocks at the end"
The recoverTimelock
is set based on the time VRFNFTRandomDraw
initialize()
is called not based on the the time startDraw()
or redraw()
is called. A malicious owner could potentially:
recoverTimelock
expires or is about to expirestartDraw()
to actually begin the rafflelastResortTimelockOwnerClaimNFT()
to claim the reward NFT before the raffle winner can claim the reward. Potentially this call to lastResortTimelockOwnerClaimNFT()
can occur within the same transaction as the above startDraw()
.The above sequence of events prevents the raffle winner from claiming the reward, thus interrupting the normal course of the contest.
In fact, a malicious raffle creator/owner could implement such a contest without ever owning the reward NFT outright. A flashloan of the NFT could be taken at the time the contest is created, and then again for startDraw()
and lastResortTimelockOwnerClaimNFT()
if these two are combined in a single transaction.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Set recoverTimelock
to a value in the future whenever startDraw()
or redraw()
is called. Alternatively, require that startDraw()
/ redraw()
be called within a certain window before recoverTimelock
expires.
#0 - hansfriese
2022-12-17T12:15:13Z
Duplicate of #132
#1 - c4-judge
2022-12-17T12:35:39Z
gzeon-c4 marked the issue as duplicate of #146
#2 - c4-judge
2022-12-17T12:35:43Z
gzeon-c4 marked the issue as satisfactory
🌟 Selected for report: 9svR6w
Also found by: 0xdeadbeef0x, BAHOZ, codeislight, deliriusz, gasperpre, trustindistrust
416.1749 USDC - $416.17
https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L173 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L162-L168
The admin/owner of VRFNFTRandomDraw
can startDraw()
a raffle, including emitting the SetupDraw
event, but in a way that ensures fulfillRandomWords()
is never called. For example:
keyHash
is not validated within coordinator.requestRandomWords()
. Providing an invalid keyHash
will allow the raffle to start but prevent the oracle from actually supplying a random value to determine the raffle result.
fulfillRandomWords()
.
In addition, the owner/admin could simply avoid ever calling startDraw()
in the first place.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Depending on the desired functionality with respect to the raffle owner, a successful callback to fulfillRandomWords()
could be a precondition of the admin/owner reclaiming the reward NFT. This would help ensure the owner does not create raffles that they intend will never pay out a reward.
#0 - c4-judge
2022-12-17T16:29:27Z
gzeon-c4 marked the issue as duplicate of #194
#1 - c4-judge
2023-01-16T09:02:55Z
gzeon-c4 marked the issue as selected for report
#2 - c4-judge
2023-01-16T09:03:02Z
gzeon-c4 changed the severity to 3 (High Risk)
#3 - c4-judge
2023-01-23T16:51:18Z
gzeon-c4 marked the issue as satisfactory
#4 - c4-judge
2023-01-23T17:42:03Z
gzeon-c4 changed the severity to 2 (Med Risk)
#5 - C4-Staff
2023-01-24T22:25:35Z
captainmangoC4 marked the issue as primary
#6 - liveactionllama
2023-02-28T19:53:31Z
Per discussion with @iainnash - adding the sponsor confirmed
label.
45.7078 USDC - $45.71
MONTH_IN_SECONDS
will be affected._requestRoll()
will never be called in cases where any if these if conditionals will be true; the reverts cannot be triggeredrequestRandomWords()
is calledredraw()
emit an event like startDraw()
does so users will be aware the raffle is being re-run.safeTransferFrom()
safeTransferFrom()
https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L127 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L187 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L216 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L271 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L295 https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L315
IERC721
interface rather than IERC721EnumerableUpgradeable
#0 - c4-judge
2022-12-17T17:24:58Z
gzeon-c4 marked the issue as grade-b
#1 - gzeoneth
2022-12-17T17:25:14Z
Possible dupe #273