Forgeries contest - 9svR6w'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: 10/77

Findings: 3

Award: $481.10

QA:
grade-b

🌟 Selected for report: 1

🚀 Solo Findings: 0

Awards

19.2206 USDC - $19.22

Labels

bug
3 (High Risk)
satisfactory
edited-by-warden
duplicate-146

External Links

Lines of code

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

Vulnerability details

Impact

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:

  1. create the raffle
  2. wait until the recoverTimelock expires or is about to expire
  3. call startDraw() to actually begin the raffle
  4. immediatly call lastResortTimelockOwnerClaimNFT() 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.

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

Tools Used

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

Findings Information

🌟 Selected for report: 9svR6w

Also found by: 0xdeadbeef0x, BAHOZ, codeislight, deliriusz, gasperpre, trustindistrust

Labels

bug
2 (Med Risk)
downgraded by judge
primary issue
satisfactory
selected for report
sponsor confirmed
M-02

Awards

416.1749 USDC - $416.17

External Links

Lines of code

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

Vulnerability details

Impact

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:

In addition, the owner/admin could simply avoid ever calling startDraw() in the first place.

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

Tools Used

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.

Awards

45.7078 USDC - $45.71

Labels

bug
grade-b
QA (Quality Assurance)
edited-by-warden
Q-05

External Links

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

  • This is actually 30 weeks, not 30 days. Validation related to MONTH_IN_SECONDS will be affected.

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

  • In the current code, _requestRoll() will never be called in cases where any if these if conditionals will be true; the reverts cannot be triggered

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

  • Incorrect comment, this is not necessarily the first time requestRandomWords() is called

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

  • Recommend that redraw() emit an event like startDraw() does so users will be aware the raffle is being re-run.

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

  • typo in comment

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

  • recommend using IERC721 safeTransferFrom()

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

  • recommend using IERC721 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

  • Can perform these calls using simply 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

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