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.).
Relationships¶
- CWE-330: Use of Insufficiently Random Values
https://cwe.mitre.org/data/definitions/330.html
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
requestIdvalues 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]...
}
}