Skip to content
Last updated: February 06, 2026

SCWE-115: Weak VRF Parameterization or Callback Validation

Stable Version v1.0

This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Relationships

Description

Using VRF services without validating requestId, sender, or subscription can let attackers spoof fulfillments or drain subscription balances. Misconfigured key hashes, gas limits, or shared subscriptions can cause predictable failures and force fallback logic that leaks randomness.

Remediation

  • Bind VRF fulfillments to tracked requestId values and trusted coordinator addresses.
  • Use dedicated subscriptions, appropriate key hashes, and sane callback gas limits.
  • Revert on unexpected fulfillments and avoid using fallback pseudo-randomness.

Examples

Vulnerable

pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract Lottery is VRFConsumerBaseV2 {
    uint256 public randomWord;

    function fulfillRandomWords(uint256, uint256[] memory words) internal override {
        randomWord = words[0]; // no requestId or sender validation
    }
}

Fixed

pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";

contract Lottery is VRFConsumerBaseV2 {
    uint256 public pending;

    function request() external { pending = COORDINATOR.requestRandomWords(/* params */); }

    function fulfillRandomWords(uint256 requestId, uint256[] memory words) internal override {
        require(requestId == pending, "unknown request");
        pending = 0;
        // use words[0]...
    }
}