The VRFHandler
smart contract serves as an intermediary for Chainlink's VRF, providing a flexible and version-agnostic interface for requesting random numbers. By decoupling your main immutable contracts from direct Chainlink VRF dependencies, you ensure they remain functional even if Chainlink upgrades or changes their VRF services (e.g., from VRF 2.0 to VRF 2.5).
Problem Addressed: If your immutable smart contract is tightly coupled with a specific VRF version, any forced migration by Chainlink could render it unusable.
The VRFHandler
mitigates this risk by allowing you to update or replace the handler without altering your main contract's logic.
- Version-Agnostic Integration: Protects your contracts from VRF version changes.
- Decoupled Architecture: Separates VRF logic from your main contracts.
- Access Control: Only authorized contracts can request random numbers.
- Configurable Parameters: Adjust VRF request settings as needed.
- Native Payment Support: Option to use native gas for VRF requests.
- Solidity: Version
0.8.26
- Chainlink Contracts: Requires
@chainlink/contracts
-
Clone the Repository
git clone https://github.com/josechifflet/chainlink-vrf-service.git cd chainlink-vrf-service
-
Install Dependencies
make install
Will install the dependencies and create a virtual environment.
Deploy the VRFHandler
contract with the following parameters:
constructor(
address _coordinator,
bytes32 _keyHash,
uint256 _subscriptionId,
uint16 _requestConfirmations,
uint32 _callbackGasLimit,
bool _nativePaymentEnabled
)
_coordinator
: Chainlink VRF Coordinator address._keyHash
: Key hash for your VRF subscription._subscriptionId
: Your VRF subscription ID._requestConfirmations
: Number of confirmations required._callbackGasLimit
: Gas limit for the callback._nativePaymentEnabled
: Use native gas for requests iftrue
.
-
Implement the Receiver Interface
Your contract should implement the
IVRFHandlerReceiver
interface:interface IVRFHandlerReceiver { function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) external; }
-
Request Random Numbers
As an authorized requester, call:
function requestRandomWords(uint32 randomWordsAmount) external returns (uint256 requestId);
randomWordsAmount
: Number of random numbers needed.
-
Handle the Callback
Implement the
fulfillRandomWords
function to receive the random numbers:function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) external override { // Your logic using _randomWords }
To adapt to VRF service changes, deploy a new VRFHandler
with updated integrations and update the handler address in your main contract (e.g., via an onlyOwner
function). This ensures continuity without modifying your main contract's immutable logic.
-
Manage Requesters:
function addAllowedRequester(address _requester) external onlyOwner; function removeAllowedRequester(address _requester) external onlyOwner;
-
Configure VRF Settings:
function setRequestConfirmations(uint16 _requestConfirmations) external onlyOwner; function setCallbackGasLimit(uint32 _callbackGasLimit) external onlyOwner;
AllowedRequesterAdded(address requester)
AllowedRequesterRemoved(address requester)
RequestConfirmationsSet(uint16 requestConfirmations)
CallbackGasLimitSet(uint32 callbackGasLimit)
- Access Control: Only add trusted contracts as allowed requesters.
- Callback Security: Ensure
fulfillRandomWords
handles inputs securely. - Upgradeable Handler Reference: Implement a method to update the
VRFHandler
address in your main contract to adapt to future changes.
This project was developed using the foundry-template by Paul Razvan Berg.
This project is licensed under the MIT License. See the LICENSE file for details.