I am using Chainlink VRF2 where I receive random numbers via a callback to this function:

function fulfillRandomWords(
    uint256, /* requestId */
    uint256[] memory randomWords
  ) internal override {
    s_randomWords = randomWords;

This function supposedly will be called by VRF coordinator but the fulfillRandomWords() function has the access modifier internal. How does the VRFCoordinator send this function a random number if it is an external contract?

1 Answer 1


In the import VRFConsumerBaseV2.sol you will see the actual function being called by the VRFCoordinator is:

function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
    if (msg.sender != vrfCoordinator) {
      revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
    fulfillRandomWords(requestId, randomWords);

This external function calls fulfillRandomWords(), and because it is inherited, fulfillRandomWords() can be internal.

Reference: VRFConsumerBaseV2.sol GitHub

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.