Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Incorrect Function Selector for Chainlink VRF Coordinator in `snek_raffle::rawFulfillRandomWords`

[H-2] Incorrect Function Selector for Chainlink VRF Coordinator in snek_raffle::rawFulfillRandomWords

Description:
The rawFulfillRandomWords function is designed to be called back by the Chainlink VRF Coordinator to provide the random words. However, the function signature does not match the expected signature for the Chainlink VRF Coordinator's callback function. The Chainlink VRF Coordinator expects a function with the signature rawFulfillRandomWords(uint256,uint256[]), but the provided function signature is rawFulfillRandomWords(uint256,uint256[1]). This will work while using the VRFCoordinatorMock contract but when working with the real implementation this wont work.

Impact:
This issue will cause the Chainlink VRF Coordinator's callback not to go through, and we would never get a winner. Because the rawFulfillRandomWords function, which chooses the winner, is never called by the VRF Coordinator contract. This failure to call back to the rawFulfillRandomWords function is a critical issue that prevents the raffle from being completed, as the winner selection process is central to the functionality of the raffle. Additionally, because of this, the raffle will always stay in calculating mode and will be unusable. This situation significantly impacts the usability and functionality of the raffle, making it impossible for participants to engage with the raffle process as intended.

Proof of Concept:

  1. Running this command in Foundry-chisel we can calculate the function Selector for rawFulfillRandomWords(uint256, uint256[]) which is the correct signature:

➜ bytes4(keccak256("rawFulfillRandomWords(uint256,uint256[])"))
Type: bytes4
└ Data: 0x1fe543e300000000000000000000000000000000000000000000000000000000
  1. But When running the singnature which is the equivalent of the snek_raffle::rawFulfillRandomWords which is rawFulfillRandomWords(uint256,uint256[1]) we get:

➜ bytes4(keccak256("rawFulfillRandomWords(uint256,uint256[1])"))
Type: bytes4
└ Data: 0x4e04d70800000000000000000000000000000000000000000000000000000000
  1. It is obvious that the 0x1fe543e3 correct selector is diffrent with the one we are sending 0x4e04d708

Recommended Mitigation: When deploying to Mainnet we change the function defenition to correct function signature:

@external
-def rawFulfillRandomWords(requestId: uint256, randomWords: uint256[MAX_ARRAY_SIZE]):
+def rawFulfillRandomWords(requestId: uint256, randomWords: DynArray[uint256, MAX_ARRAY_SIZE]):
"""The function the VRF Coordinator calls back to to provide the random words."""
assert msg.sender == VRF_COORDINATOR.address, ERROR_NOT_COORDINATOR
self.fulfillRandomWords(requestId, randomWords)

The snek_raffle::fulfillRandomWords function should also be changed as below:

@internal
-def fulfillRandomWords(request_id: uint256, random_words: uint256[MAX_ARRAY_SIZE]):
+def fulfillRandomWords(request_id: uint256, _random_words: DynArray[uint256, MAX_ARRAY_SIZE]):
.
.
.
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect Function Selector for Chainlink VRF

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.