Forgeries contest - 0xdeadbeef0x'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: 12/77

Findings: 2

Award: $365.84

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 9svR6w

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

Labels

bug
2 (Med Risk)
satisfactory
duplicate-101

Awards

320.1346 USDC - $320.13

External Links

Lines of code

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

Vulnerability details

Impact

Owners can leverage the insufficient funds in Chainlink subscription to successfully call startDraw and not appoint a winner.

This is medium because theoretically, users can add funds to the subscriptions if such a case is noticed as anyone can fund a subscription. It is less likely, because it would require them to pay extra funds for a chance to win the raffle.

Proof of Concept

The bug is because fulfillRandomWords will revert. This is due to Chainlink calculating that the payment is more than the balance from the subscription: https://github.com/smartcontractkit/chainlink/blob/286a65065fcfa5e1b2362745079cdc218e40e68d/contracts/src/v0.8/VRFCoordinatorV2.sol#L595

(See previous submission: Raffle is insolvent if owner cancels Chainlink subscription [194])

Foundry POC

The following POC demonstrates the creation of a raffle and a successful startDraw. No funding of the subscription. Users will not able to call hasUserWon After lock period. owner will withdraw the NFT.

Add the following test to VRFNFTRandomDraw.t.sol: https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/test/VRFNFTRandomDraw.t.sol#L541

function test_insufficiantFunding() public { 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 hours, recoverTimelock: 2 weeks, keyHash: bytes32( 0x79d3d8832d904592c0bf9818b621522c988bb8b0c05cdc3b15aea1b6e8db0c15 ), subscriptionId: subscriptionId }) ); vm.label(consumerAddress, "drawing instance"); mockCoordinator.addConsumer(subscriptionId, consumerAddress); VRFNFTRandomDraw drawing = VRFNFTRandomDraw(consumerAddress); targetNFT.setApprovalForAll(consumerAddress, true); // Start draw uint256 drawingId = drawing.startDraw(); vm.stopPrank(); // Revert because insufficiant funds vm.expectRevert(); mockCoordinator.fulfillRandomWords(drawingId, consumerAddress); vm.warp(2 weeks); // forward two weeks // validate no number was chosen (Although start draw was called) vm.expectRevert(IVRFNFTRandomDraw.NEEDS_TO_HAVE_CHOSEN_A_NUMBER.selector); drawing.hasUserWon(address(this)); vm.prank(admin); drawing.lastResortTimelockOwnerClaimNFT(); // validate admin received his NFT assertEq(targetNFT.balanceOf(admin), 1); }

To run the POC, execute: forge test -m "test_insufficiantFunding" -vvvv

Tools Used

VS Code, Foundry

Validate in the initialization of the contract or the startDraw that the amount of funds currently in the subscription are sufficient for a minimum amount of redraws (related to the lock period). If possible, automatically transfer a portion of the revenue of the raffle tickets to pay for the subscription funding.

Here is the function that can receive the amount of funds in the subscription: https://github.com/smartcontractkit/chainlink/blob/286a65065fcfa5e1b2362745079cdc218e40e68d/contracts/src/v0.8/VRFCoordinatorV2.sol#L685

#0 - c4-judge

2022-12-17T13:52:26Z

gzeon-c4 marked the issue as duplicate of #194

#1 - c4-judge

2023-01-23T16:51:13Z

gzeon-c4 marked the issue as satisfactory

Awards

45.7078 USDC - $45.71

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
satisfactory
sponsor disputed
Q-14

External Links

Lines of code

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

Vulnerability details

Impact

The owner can decide not to redraw. Therefore if no winner is selected the first time, the owner can wait for the lock period to end and get their NFT back.

Proof of Concept

redraw function is set with the onlyOwner modifier. It can only be called by the owner. https://github.com/code-423n4/2022-12-forgeries/blob/fc271cf20c05ce857d967728edfb368c58881d85/src/VRFNFTRandomDraw.sol#L203:

function redraw() external onlyOwner returns (uint256) {

Tools Used

VS Code

The protocol has placed a lot of trust in the owner. Users should be able to call redraw as well.

#0 - c4-judge

2022-12-17T16:00:13Z

gzeon-c4 marked the issue as primary issue

#1 - c4-judge

2022-12-17T16:00:26Z

gzeon-c4 marked the issue as satisfactory

#2 - gzeoneth

2022-12-17T16:01:15Z

I think this is low risk given the permissioned design of the contract, will wait for sponsor comment.

#3 - iainnash

2022-12-19T20:04:35Z

@gzeoneth Agreed with low/QA. The contract is permissioned due to the dependency on chainlink and a relative level of trust of the owner.

#4 - c4-sponsor

2023-01-01T18:32:22Z

iainnash marked the issue as sponsor disputed

#5 - c4-judge

2023-01-07T17:01:45Z

gzeon-c4 changed the severity to QA (Quality Assurance)

#6 - c4-judge

2023-01-07T17:02:34Z

gzeon-c4 marked the issue as grade-b

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