# Chainlink VRF Source: https://docs.chain.link/vrf **Chainlink VRF (Verifiable Random Function)** is a provably fair and verifiable random number generator (RNG) that enables smart contracts to access random values without compromising security or usability. For each request, Chainlink VRF generates one or more random values and cryptographic proof of how those values were determined. The proof is published and verified onchain before any consuming applications can use it. This process helps ensure that results cannot be tampered with or manipulated by any single entity including oracle operators, smart contract developers, users, miners, or block builders\*. \*In the unlikely event that an adversary compromises VRF's randomness-generating secret key and obtains the ability to construct blocks on the target chain, they could strongly bias the result. > **NOTE: Migrate to V2.5** > > Follow the [migration guide](/vrf/v2-5/migration-from-v2) to learn how VRF has changed in V2.5 and to get example > code. Use Chainlink VRF to build reliable smart contracts for any applications that rely on unpredictable outcomes: - Building blockchain games and NFTs. - Random assignment of duties and resources. For example, randomly assigning judges to cases. - Choosing a representative sample for consensus mechanisms. VRF v2.5 includes [all the original benefits of v2](https://blog.chain.link/vrf-v2-mainnet-launch/) and the following additional benefits: - Easier upgrades to future versions. - The option to pay for requests in either LINK or native tokens. Learn how to [migrate to VRF v2.5](/vrf/v2-5/migration-from-v2). For help with your specific use case, [contact us](https://chain.link/contact) to connect with one of our Solutions Architects. You can also ask questions about Chainlink VRF on [Stack Overflow](https://stackoverflow.com/questions/ask?tags=chainlink). ## Two methods to request randomness Similarly to VRF v2, VRF v2.5 will offer two methods for requesting randomness: - [Subscription](/vrf/v2-5/overview/subscription): Create a subscription account and fund its balance with either native tokens or LINK. You can then connect multiple consuming contracts to the subscription account. When the consuming contracts request randomness, the transaction costs are calculated after the randomness requests are fulfilled and the subscription balance is deducted accordingly. This method allows you to fund requests for multiple consumer contracts from a single subscription. - [Direct funding](/vrf/v2-5/overview/direct-funding): Consuming contracts directly pay with either native tokens or LINK when they request random values. You must directly fund your consumer contracts and ensure that there are enough funds to pay for randomness requests. ## Choosing the correct method Depending on your use case, one method might be more suitable than another. Consider the following characteristics when you choose a method: | [Subscription method](/vrf/v2-5/overview/subscription) | [Direct funding method](/vrf/v2-5/overview/direct-funding) | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Currently available on VRF v2.5 for all supported networks. | Currently available on VRF v2.5 for all supported networks. | | Suitable for regular requests | Suitable for infrequent one-off requests | | Supports multiple VRF consuming contracts connected to one subscription account | Each VRF consuming contract directly pays for its requests | | VRF costs are calculated after requests are fulfilled and then deducted from the subscription balance. Learn [how VRF costs are calculated for the subscription method](/vrf/v2-5/overview/subscription). | VRF costs are estimated and charged at request time, which may make it easier to transfer the cost of VRF to the end user. Learn [how VRF costs are calculated for the direct funding method](/vrf/v2-5/overview/direct-funding). | | Reduced gas overhead and more control over the maximum gas price for requests | Higher gas overhead than the subscription method | | More random values returned per single request. See the maximum random values per request for the [V2.5 subscription supported networks](/vrf/v2-5/supported-networks). | Fewer random values returned per single request than the subscription method, due to higher overhead. See the maximum random values per request and gas overhead for the [V2 direct funding supported networks](/vrf/v2-5/supported-networks). | | You don't have to estimate costs precisely for each request. Ensure that the subscription account has enough funds. | You must estimate transaction costs carefully for each request to ensure the consuming contract has enough funds to pay for the request. | | Requires a subscription account | No subscription account required | | VRF costs are billed to your subscription account | No refunds for overpayment after requests are completed | ## Supported networks The contract addresses and gas price limits are different depending on which method you use to get randomness. You can find the configuration, addresses, and limits for each method on the [Supported networks](/vrf/v2-5/supported-networks) page. To learn when VRF v2.5 becomes available on more networks, follow us on [Twitter](https://twitter.com/chainlink) or sign up for our [mailing list](/resources/developer-communications?parent=vrf). --- # Getting Started with Chainlink VRF V2.5 Source: https://docs.chain.link/vrf/v2-5/getting-started > **NOTE: Requirements** > > This guide assumes that you have basic knowledge about writing and deploying smart contracts. If you are new to smart > contract development, learn how to [Deploy Your First Smart Contract](/quickstarts/deploy-your-first-contract) before > you begin. In this guide, you will learn about generating randomness on blockchains. This includes learning how to implement a Request and Receive cycle with Chainlink oracles and how to consume random numbers with Chainlink VRF in smart contracts. ## How is randomness generated on blockchains? What is Chainlink VRF? Randomness is very difficult to generate on blockchains. This is because every node on the blockchain must come to the same conclusion and form a consensus. Even though random numbers are versatile and useful in a variety of blockchain applications, they cannot be generated natively in smart contracts. The solution to this issue is [**Chainlink VRF**](/vrf), also known as Chainlink Verifiable Random Function. ## What is the Request and Receive cycle? The [Data Feeds Getting Started](/data-feeds/getting-started) guide explains how to consume Chainlink Data Feeds, which consist of reference data posted onchain by oracles. This data is stored in a contract and can be referenced by consumers until the oracle updates the data again. Randomness, on the other hand, cannot be reference data. If the result of randomness is stored onchain, any actor could retrieve the value and predict the outcome. Instead, randomness must be requested from an oracle, which generates a number and a cryptographic proof. Then, the oracle returns that result to the contract that requested it. This sequence is known as the **[Request and Receive cycle](/architecture-overview/architecture-request-model)**. ## What is the payment process for generating a random number? VRF requests receive funding from subscription accounts. The [Subscription Manager](https://vrf.chain.link) lets you create an account and pre-pay for VRF requests, so that funding of all your application requests are managed in a single location. To learn more about VRF requests funding, see [Subscription limits](/vrf/v2-5/overview/subscription#subscription-limits). ## How can I use Chainlink VRF? In this section, you will create an application that uses Chainlink VRF to generate randomness. The contract used in this application has a [*Game of Thrones*](https://en.wikipedia.org/wiki/Game_of_Thrones) theme. After the contract requests randomness from Chainlink VRF, the result of the randomness will transform into a number between 1 and 20, mimicking the rolling of a 20 sided die. Each number represents a *Game of Thrones* house. If the dice land on the value 1, the user is assigned house Targaryan, 2 for Lannister, and so on. A full list of houses can be found [here](https://gameofthrones.fandom.com/wiki/Great_House). When rolling the dice, it uses an `address` variable to track which address is assigned to each house. The contract has the following functions: - `rollDice`: This submits a randomness request to Chainlink VRF - `fulfillRandomWords`: The function that the Oracle uses to send the result back - `house`: To see the assigned house of an address **Note**: to jump straight to the entire implementation, you can [open the VRFD20.sol contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/VRFD20.sol) in Remix. ### Create and fund a subscription Chainlink VRF requests receive funding from subscription accounts. The [Subscription Manager](https://vrf.chain.link) lets you create an account and pre-pay your use of Chainlink VRF requests. For this example, create a new subscription on the Sepolia testnet as explained [here](/vrf/v2-5/subscription/create-manage). Your subscription has two balances - one for LINK and one for the native token you're using (in this case, Sepolia ETH). You can choose to pay for VRF requests using either balance. ### Importing contracts Chainlink maintains a [library of contracts](https://github.com/smartcontractkit/chainlink/tree/contracts-v1.3.0/contracts) that make consuming data from oracles easier. For Chainlink VRF, you will use: - [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) that must be imported and extended from the contract that you create. - [`VRFV2PlusClient`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol) to format your requests to VRF. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract VRFD20 is VRFConsumerBaseV2Plus { } ``` ### Contract variables This example is adapted for [Sepolia testnet](/vrf/v2-5/supported-networks#ethereum-sepolia-testnet) but you can change the configuration and make it run for any [supported network](/vrf/v2-5/supported-networks). ```solidity uint256 s_subscriptionId; address vrfCoordinator = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B; bytes32 s_keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; uint32 callbackGasLimit = 40000; uint16 requestConfirmations = 3; uint32 numWords = 1; ``` - `uint256 s_subscriptionId`: The subscription ID that this contract uses for funding requests. Initialized in the `constructor`. - `address vrfCoordinator`: The address of the Chainlink VRF Coordinator contract. - `bytes32 s_keyHash`: The gas lane key hash value, which is the maximum gas price you are willing to pay for a request in wei. It functions as an ID of the offchain VRF job that runs in response to requests. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords` function. It must be less than the `maxGasLimit` on the coordinator contract. Adjust this value for larger requests depending on how your `fulfillRandomWords` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your subscription is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` value on the coordinator contract. For Sepolia, the `minimumRequestBlockConfirmations` value is 3. You can check this and the other configuration values on the coordinator contract by querying [the `s_config` value in the Sepolia Etherscan block explorer](https://sepolia.etherscan.io/address/0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B#readContract#F12). - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. In this example, each transaction requests one random value. To keep track of addresses that roll the dice, the contract uses mappings. [Mappings](https://medium.com/upstate-interactive/mappings-in-solidity-explained-in-under-two-minutes-ecba88aff96e) are unique key-value pair data structures similar to hash tables in Java. ```solidity mapping(uint256 => address) private s_rollers; mapping(address => uint256) private s_results; ``` - `s_rollers` stores a mapping between the `requestID` (returned when a request is made), and the address of the roller. This is so the contract can keep track of who to assign the result to when it comes back. - `s_results` stores the roller and the result of the dice roll. ### Initializing the contract The subscription ID must be initialized in the `constructor` of the contract. To use `VRFConsumerBaseV2Plus` properly, you must also pass the VRF coordinator address into its constructor. The address that creates the smart contract is the owner of the contract. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract VRFD20 is VRFConsumerBaseV2Plus { // variables // ... // constructor constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) { s_subscriptionId = subscriptionId; } ... } ``` ### `rollDice` function The `rollDice` function will complete the following tasks: 1. Check if the roller has already rolled since each roller can only ever be assigned to a single house. 2. Request randomness by calling the VRF coordinator. 3. Store the `requestId` and roller address. 4. Emit an event to signal that the dice is rolling. You must add a `ROLL_IN_PROGRESS` constant to signify that the dice has been rolled but the result is not yet returned. Also add a `DiceRolled` event to the contract. Only the owner of the contract can execute the `rollDice` function. This `rollDice` function is configured so that you pay for VRF requests using LINK by default. If you want to pay for your VRF request with Sepolia ETH instead, set `nativePayment` to `true`. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract VRFD20 is VRFConsumerBaseV2Plus { // variables uint256 private constant ROLL_IN_PROGRESS = 42; // ... // events event DiceRolled(uint256 indexed requestId, address indexed roller); // ... // ... // { constructor } // ... // rollDice function function rollDice(address roller) public onlyOwner returns (uint256 requestId) { require(s_results[roller] == 0, "Already rolled"); // Will revert if subscription is not set and funded. requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: s_keyHash, subId: s_subscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, // Set nativePayment to true to pay for VRF requests with Sepolia ETH instead of LINK extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) }) ); s_rollers[requestId] = roller; s_results[roller] = ROLL_IN_PROGRESS; emit DiceRolled(requestId, roller); } } ``` ### `fulfillRandomWords` function `fulfillRandomWords` is a special function defined within the `VRFConsumerBaseV2Plus` contract that our contract extends from. The coordinator sends the result of our generated `randomWords` back to `fulfillRandomWords`. You will implement some functionality here to deal with the result: 1. Change the result to a number between 1 and 20 inclusively. Note that `randomWords` is an array that could contain several random values. In this example, request 1 random value. 2. Assign the transformed value to the address in the `s_results` mapping variable. 3. Emit a `DiceLanded` event. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract VRFD20 is VRFConsumerBaseV2Plus { // ... // { variables } // ... // events // ... event DiceLanded(uint256 indexed requestId, uint256 indexed result); // ... // { constructor } // ... // ... // { rollDice function } // ... // fulfillRandomWords function function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { // transform the result to a number between 1 and 20 inclusively uint256 d20Value = (randomWords[0] % 20) + 1; // assign the transformed value to the address in the s_results mapping variable s_results[s_rollers[requestId]] = d20Value; // emitting event to signal that dice landed emit DiceLanded(requestId, d20Value); } } ``` ### `house` function Finally, the `house` function returns the house of an address. To have a list of the house's names, create the `getHouseName` function that is called in the `house` function. ```solidity // SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; contract VRFD20 is VRFConsumerBaseV2Plus { // ... // { variables } // ... // ... // { events } // ... // ... // { constructor } // ... // ... // { rollDice function } // ... // ... // { fulfillRandomWords function } // ... // house function function house(address player) public view returns (string memory) { // dice has not yet been rolled to this address require(s_results[player] != 0, "Dice not rolled"); // not waiting for the result of a thrown dice require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress"); // returns the house name from the name list function return getHouseName(s_results[player]); } // getHouseName function function getHouseName(uint256 id) private pure returns (string memory) { // array storing the list of house's names string[20] memory houseNames = [ "Targaryen", "Lannister", "Stark", "Tyrell", "Baratheon", "Martell", "Tully", "Bolton", "Greyjoy", "Arryn", "Frey", "Mormont", "Tarley", "Dayne", "Umber", "Valeryon", "Manderly", "Clegane", "Glover", "Karstark" ]; // returns the house name given an index return houseNames[id - 1]; } } ``` [Open VRFD20.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/VRFD20.sol) You have now completed all necessary functions to generate randomness and assign the user a *Game of Thrones* house. We've added a few helper functions in there to make using the contract easier and more flexible. You can deploy and interact with the complete contract in Remix. ## How do I deploy to testnet? You will deploy this contract on the Sepolia test network. You must have some Sepolia testnet ETH in your MetaMask account to pay for the gas for each contract interaction with the Sepolia network. You can choose to pay for your VRF requests in either Sepolia ETH or testnet LINK. The `rollDice` function is written to use LINK by default. If you want to change to using Sepolia, set `nativePayment` to `true` before deploying your contract. You can request both testnet LINK and testnet ETH from [faucets.chain.link/sepolia](https://faucets.chain.link/sepolia). Testnet ETH is also available from several [public faucets](https://faucetlink.to/sepolia). This deployment is slightly different than the example in the [Deploy Your First Contract](/quickstarts/deploy-your-first-contract) guide. In this case, you pass in parameters to the constructor upon deployment. Once compiled, you'll see a dropdown menu that looks like this in the deploy pane: ![Remix contract selected](/images/vrf/v2-5/select-vrfd20-contract.png) Select the `VRFD20` contract or the name that you gave to your contract. Click the caret arrow on the right hand side of **Deploy** to expand the parameter fields, and paste your subscription ID. ![Remix contract parameters to deploy](/images/vrf/v2-5/deploy-with-sub-id.png) Then click the `Deploy` button and use your MetaMask account to confirm the transaction. > **NOTE: Address, Key Hashes and more** > > For a full reference of the addresses, key hashes and fees for each network, see [VRF Supported > Networks](/vrf/v2-5/supported-networks). At this point, your contract should be successfully deployed. However, it can't request anything because it is not yet approved to use the LINK or Sepolia ETH balance in your subscription. If you click `rollDice`, the transaction will revert. ## How do I add my contract to my subscription account? After you deploy your contract, you must add it as an approved consumer contract so it can use the subscription balance when requesting for randomness. 1. Find your contract address in Remix under **Deployed Contracts** on the bottom left, and copy the contract address: ![Copy Remix contract address](/images/vrf/v2-5/copy-contract-address.png) 2. Go to the [Subscription Manager](https://vrf.chain.link), open the details page for your subscription, and add your deployed contract address to the list of consumers: ![Add a consumer to your VRF subscription](/images/vrf/v2-5/ui-add-consumer.png) ## How do I test `rollDice`? After you open the deployed contract tab in the bottom left, the function buttons are available. Find `rollDice` and click the caret to expand the parameter fields. Enter an Ethereum address to specify a "dice roller", and click `rollDice`. It takes a few minutes for the transaction to confirm and the response to be sent back. You can get your house by clicking the `house` function button with the address passed in `rollDice`. After the response is sent back, you'll be assigned a *Game of Thrones* house! ## Further reading To read more about generating random numbers in Solidity, read our blog posts: - [35+ Blockchain RNG Use Cases Enabled by Chainlink VRF](https://blog.chain.link/blockchain-rng-use-cases-enabled-by-chainlink-vrf/) - [How to Build Dynamic NFTs on Polygon](https://blog.chain.link/how-to-build-dynamic-nfts-on-polygon/) - [Scaling Onchain Verifiable Randomness With Chainlink VRF v2.5](https://blog.chain.link/introducing-vrf-v2-5/) --- # Migrating from VRF v2 Source: https://docs.chain.link/vrf/v2-5/migration-from-v2 VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Learn more about VRF V2.5](https://blog.chain.link/introducing-vrf-v2-5/). ## Benefits of VRF v2.5 Chainlink VRF v2.5 includes [all the same key benefits as VRF v2](https://blog.chain.link/vrf-v2-mainnet-launch/), along with the following additional benefits and changes: - Easier upgrades to future versions by using the new `setCoordinator` function - The option to pay for requests in either LINK or native tokens - New, flexible request format in `requestRandomWords` to make any future upgrades easier ## Code changes VRF v2.5 introduces a new request format and the `setCoordinator` function. See the [full migration walkthrough](#migration-walkthrough) or the code example for more details. ### New request format The request format for VRF v2.5 has changed: ### Subscription The `requestRandomWords` function now uses `VRFV2PlusClient.RandomWordsRequest` with an object labeling each part of the request: ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) }) ); ``` You must include a value for the new `extraArgs` key, which allows you to add extra arguments related to new VRF features. Use the `nativePayment` argument to enable or disable payment in native tokens. ### Direct funding The `requestRandomness` function in the wrapper contract requires a new `extraArgs` argument that allows you to add extra arguments related to new VRF features. Use the `nativePayment` argument to enable or disable payment in native tokens. Additionally, the `requestRandomness` function now returns two arguments instead of one: the request ID and the request price. ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ); (uint256 reqId, uint256 reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` ### setCoordinator function Add the `setCoordinator` function to your contract so that you can easily update the VRF coordinator for future VRF releases. ### Subscription ID type change Note that the subscription ID has changed types from `uint64` in VRF V2 to `uint256` in VRF V2.5. ## Billing changes You have the option to use either native tokens or LINK to pay for VRF requests. To accommodate this, the premium fee has changed from a flat LINK premium amount per request, to a percentage-based premium per request. Refer to the [Billing](/vrf/v2-5/billing) page for more details. To find out the new premium percentages for the networks you use, see the [Supported Networks](/vrf/v2-5/supported-networks) page. For direct funding, the configurations for overhead gas have changed: - The amount of wrapper overhead gas is reduced compared to V2. - The amount of coordinator overhead gas used varies depending on the network used for your request, whether you're paying in LINK or native tokens, and how many random values you want in each VRF request. Refer to the [Billing](/vrf/v2-5/billing) page for more details and examples, and see the new configurations on the [Supported Networks](/vrf/v2-5/supported-networks) page. ## Migration walkthrough VRF v2.5 currently supports subscriptions and direct funding on all [supported networks](/vrf/v2-5/supported-networks). To migrate, you need to [update your existing smart contract code](#update-your-code) and redeploy your contracts. If using subscriptions, [create and fund a new VRF v2.5 subscription](/vrf/v2-5/subscription/create-manage). For direct funding, deploy the [`DirectFundingConsumer`](/samples/VRF/v2-5/DirectFundingConsumer.sol) example: [Open DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) ### Update your code To modify your existing smart contract code to work with VRF v2.5, complete the following changes: ### Subscription 1. Import the [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) contract and remove the v2 `VRFConsumerBaseV2` import. 2. Import the VRF v2.5 coordinator, [`VRFCoordinatorV2_5`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol), and update any old references to the VRF V2 coordinator in your contract. 3. Add a `VRFConsumerBaseV2Plus` constructor, passing in the VRF coordinator address for the network you're using. 4. Update your `requestRandomWords` function calls to reflect the new request structure for VRF v2.5. Make sure to include the new `extraArgs` part of the `VRFV2PlusClient.RandomWordsRequest` object, and specify whether or not you want to pay for VRF requests using native tokens: ### LINK ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) }) ); ``` ### Native tokens ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) }) ); ``` 5. When using the [`@chainlink/contracts`](https://www.npmjs.com/package/@chainlink/contracts/v/1.1.1) package version 1.1.1 and later, update your `fulfillRandomWords` function signature to match the `VRFConsumerBaseV2Plus` contract, which has changed to: ``` function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) ``` In the `@chainlink/contracts` package version 1.1.0 and earlier, the `randomWords` parameter has a `memory` storage location. ### Direct funding 1. Import the [`VRFV2PlusWrapperConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) contract and remove the v2 `VRFV2WrapperConsumerBase` import. 2. Add a `VRFV2PlusWrapperConsumerBase` constructor, passing in the VRF wrapper address for the network you're using. Unlike in V2, you don't have to pass the LINK token address to the constructor. 3. If you're paying for requests with LINK, you can still call the `requestRandomness` function. However, if you're paying with native tokens, call the `requestRandomnessPayInNative` function instead. Both functions require one additional parameter, `extraArgs`. Use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens: ### LINK ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ); (uint256 reqId, uint256 reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` ### Native tokens ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: true}) ); (uint256 reqId, uint256 reqPrice) = requestRandomnessPayInNative( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` 4. The V2.5 `requestRandomness` and `requestRandomnessPayInNative` functions both return a tuple: `(uint256 requestId, uint256 requestPrice)`. Adjust your `requestRandomWords` function or any other functions in your code where you call the V2.5 wrapper's `requestRandomness` or `requestRandomnessPayInNative` functions. 5. Make sure your contract has a withdraw function for both native tokens and LINK. Both are included in the [direct funding example code](#direct-funding-example-code) and the [`VRFV2PlusWrapperConsumerExample`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol) contract. ### Compare example code #### Subscription example code The example `SubscriptionConsumer` contract shows the migration steps above, applied to the example code from [this VRF V2 tutorial](/vrf/v2/subscription/examples/get-a-random-number#analyzing-the-contract). Both of these examples use the subscription method. Open the full example `SubscriptionConsumer` contract: [Open SubscriptionConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionConsumer.sol) Compare the major changes between V2.5 and V2: ### VRF V2.5 example code ```solidity // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity 0.8.19; ///// UPDATE IMPORTS TO V2.5 ///// import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; ... /\*\* - THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. - THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. - DO NOT USE THIS CODE IN PRODUCTION. \*/ ///// INHERIT NEW CONSUMER BASE CONTRACT ///// contract SubscriptionConsumer is VRFConsumerBaseV2Plus { ... ///// No need to declare a coordinator variable ///// ///// Use the `s_vrfCoordinator` from VRFConsumerBaseV2Plus.sol ///// ///// SUBSCRIPTION ID IS NOW UINT256 ///// uint256 s_subscriptionId; ... ///// USE NEW KEYHASH FOR VRF 2.5 GAS LANE ///// // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2-5/supported-networks bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; ... ///// USE NEW CONSUMER BASE CONSTRUCTOR ///// constructor( ///// UPDATE TO UINT256 ///// uint256 subscriptionId ) VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) { s_subscriptionId = subscriptionId; } function requestRandomWords() external onlyOwner returns (uint256 requestId) { ///// UPDATE TO NEW V2.5 REQUEST FORMAT ///// // To enable payment in native tokens, set nativePayment to true. // Use the `s_vrfCoordinator` from VRFConsumerBaseV2Plus.sol requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_subscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ) }) ); ... } ... } ``` ### VRF V2 example code ```solidity // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.7; ///// USES V2 IMPORTS ///// import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; /\*\* - THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. - THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. - DO NOT USE THIS CODE IN PRODUCTION. \*/ ///// USES V2 CONSUMER BASE CONTRACT ///// contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner { ... ///// OLD TYPE FOR SUBSCRIPTION ID ///// uint64 s_subscriptionId; ... ///// KEYHASH FOR VRF V2 GAS LANE ///// // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2/subscription/supported-networks/#configurations bytes32 keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; ... ///// USES V2 CONSUMER BASE AND COORDINATOR CONSTRUCTORS ///// constructor( uint64 subscriptionId ) VRFConsumerBaseV2(0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625) ConfirmedOwner(msg.sender) { COORDINATOR = VRFCoordinatorV2Interface( 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625 ); s_subscriptionId = subscriptionId; } ... function requestRandomWords() external onlyOwner returns (uint256 requestId) { ///// USES V2 REQUEST FORMAT ///// requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); ... } ... } ``` #### Direct funding example code The example `DirectFundingConsumer` contract shows the migration steps above, applied to the example code from [this VRF V2 tutorial](/vrf/v2/direct-funding/examples/get-a-random-number#analyzing-the-contract). Both of these examples use the direct funding method. Open the full example `DirectFundingConsumer` contract: [Open DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) Compare the major changes between V2.5 and V2: ### VRF V2.5 example code ```solidity // SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity 0.8.20; ///// UPDATE IMPORTS TO V2.5 ///// import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {VRFV2PlusWrapperConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol"; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ ///// INHERIT NEW WRAPPER CONSUMER BASE CONTRACT ///// contract DirectFundingConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { ... ///// USE NEW WRAPPER CONSUMER BASE CONSTRUCTOR ///// constructor() ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(wrapperAddress) ///// ONLY PASS IN WRAPPER ADDRESS ///// {} function requestRandomWords( bool enableNativePayment ) external onlyOwner returns (uint256) { ///// UPDATE TO NEW V2.5 REQUEST FORMAT: ADD EXTRA ARGS ///// bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment}) ); uint256 requestId; uint256 reqPrice; if (enableNativePayment) { ///// USE THIS FUNCTION TO PAY IN NATIVE TOKENS ///// (requestId, reqPrice) = requestRandomnessPayInNative( callbackGasLimit, requestConfirmations, numWords, extraArgs ///// PASS IN EXTRA ARGS ///// ); } else { ///// USE THIS FUNCTION TO PAY IN LINK ///// (requestId, reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ///// PASS IN EXTRA ARGS ///// ); } ... return requestId; } ... } ``` ### VRF V2 example code ```solidity // SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity ^0.8.7; ///// USES V2 IMPORTS ///// import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {VRFV2WrapperConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol"; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; /\*\* - THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. - THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. - DO NOT USE THIS CODE IN PRODUCTION. \*/ ///// USES V2 WRAPPER CONSUMER BASE CONTRACT ///// contract VRFv2DirectFundingConsumer is VRFV2WrapperConsumerBase, ConfirmedOwner { ... ///// USES V2 WRAPPER CONSUMER BASE CONSTRUCTOR ///// constructor() ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(linkAddress, wrapperAddress) ///// TWO PARAMETERS ///// {} function requestRandomWords() external onlyOwner returns (uint256 requestId) { ///// USES V2 REQUEST FORMAT ///// requestId = requestRandomness( callbackGasLimit, requestConfirmations, numWords ); ... return requestId; } ... } ``` --- # Migrating from VRF v1 Source: https://docs.chain.link/vrf/v2-5/migration-from-v1 VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Learn more about VRF V2.5](https://blog.chain.link/introducing-vrf-v2-5/). ## Comparing VRF v1 to VRF v2.5 Chainlink VRF v2.5 includes several improvements and changes to the way you fund and request randomness for your smart contracts: - You have the option to manage payment for your VRF requests by pre-funding a subscription account, or to directly fund your consuming contracts as you do with VRF V1. [Compare subscription and direct funding](/vrf/#choosing-the-correct-method). - VRF v2.5 introduces the option to pay for requests in either LINK or native tokens. This choice is available for both subscription and direct funding. ### New billing options - **Native billing:** You have the option to use either native tokens or LINK to pay for VRF requests. Instead of a flat LINK fee per request, there is percentage-based premium fee applied to each request. See the [Billing](/vrf/v2-5/billing) page for more details. To find out the premium percentages for the networks you use, see the [Supported Networks](/vrf/v2-5/supported-networks) page. - **Subscription management:** Chainlink VRF v2.5 has a [Subscription Manager](https://vrf.chain.link) application that allows smart contract applications to pre-fund multiple requests for randomness using one subscription account. This reduces the gas fees for VRF requests by eliminating the need to transfer funds for each individual request. You transfer funds to the subscription balance only when it requires additional funding. - **Unified Billing - Delegate Subscription Balance to Multiple Addresses:** Chainlink VRF v2.5 allows up to 100 smart contract addresses to fund their requests for verifiable randomness from a single subscription account, which is managed by the subscription owner. - **Variable Callback Gas Limit:** Chainlink VRF v2.5 lets you adjust the callback gas limit when your smart contract application receives verifiable randomness. Consuming contracts can execute more complex logic in the callback request function that receives the random values. Tasks involving the delivered randomness are handled during the response process. The new gas limits are higher than the VRF V1 limit, and vary depending on the underlying blockchain you use. See the gas limits on the [VRF Supported Networks](/vrf/v2-5/supported-networks) page. - **More configuration capability:** You can define how many block confirmations must pass before verifiable randomness is generated and delivered onchain when your application makes a request transaction. The range is from 3 to 200 blocks. VRF V1 always waited 10 blocks on Ethereum before delivering onchain randomness. Select a value that protects your application from block re-organizations while still providing sufficiently low latency from request to response. See the [Security Considerations](/vrf/v2-5/security) page to learn more. - **Multiple Random Outputs in a Single Request:** In VRF v2.5, you can request multiple random numbers (multi-word) in a single onchain transaction, which reduces gas costs. The fulfillment is also a single transaction, which reduces the latency of responses. For direct funding, the configurations for overhead gas have changed: - The amount of wrapper overhead gas is reduced compared to V2. - The amount of coordinator overhead gas used varies depending on the network used for your request, whether you're paying in LINK or native tokens, and how many random values you want in each VRF request. See the [Billing](/vrf/v2-5/billing) page for more details and examples. The new configurations are listed in the [Supported Networks](/vrf/v2-5/supported-networks) page. ### Updating your applications to use VRF v2.5 You have the option to manage payment for your VRF requests with a subscription account, or to directly fund your consuming contracts as you do with VRF V1. [Compare subscription and direct funding](/vrf/#choosing-the-correct-method). ### Subscription To modify your existing smart contract code to work with VRF v2.5, complete the following changes. See the [Get a Random Number](/vrf/v2-5/subscription/get-a-random-number) guide for an example. 1. Set up and fund a subscription in the Subscription Manager at [vrf.chain.link](https://vrf.chain.link). [Open the Subscription Manager](https://vrf.chain.link) 2. Add the following imports to your contract: - [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol). Remove the v1 `VRFConsumerBase.sol` import. `VRFConsumerBaseV2Plus` includes the `fulfillRandomWords` function. The `VRFConsumerBaseV2Plus` contract imports the `IVRFCoordinatorV2Plus` interface, which includes the `requestRandomWords` function. - [`VRFV2PlusClient`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev//libraries/VRFV2PlusClient.sol) is a library used to format your VRF requests. ```solidity import { VRFConsumerBaseV2Plus } from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import { VRFV2PlusClient } from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; ``` 3. Add a `VRFConsumerBaseV2Plus` constructor, passing in the LINK token address for the network you're using, as shown in the [Get a Random Number](/vrf/v2-5/subscription/get-a-random-number) example. 4. Change `requestRandomness` function calls to `requestRandomWords`. The `requestRandomWords` function requires several additional parameters. The `extraArgs` key allows you to add extra arguments related to new VRF features. Use the `nativePayment` argument to enable or disable payment in native tokens. ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) }) ); ``` 5. Change `fulfillRandomness` function calls to `fulfillRandomWords`. Update the call to handle the returned `uint256[]` array instead of the single `uint256` variable. 6. Use the `setCoordinator` function in your contract so that you can easily update the VRF coordinator for future VRF releases. This function is inherited from the [`IVRFCoordinatorV2Plus`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol) interface. ### Direct funding To modify your existing smart contract code to work with VRF v2.5, complete the following changes. See the [Get a Random Number](/vrf/v2-5/direct-funding/get-a-random-number) guide for an example. 1. Import and inherit the [`VRFV2PlusWrapperConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) contract and remove the v1 `VRFConsumerBase.sol` import. This contract includes the `fulfillRandomWords` function. 2. Add a `VRFV2PlusWrapperConsumerBase` constructor, passing in the VRF wrapper address for the network you're using, as shown in the [Get a Random Number](/vrf/v2-5/direct-funding/get-a-random-number) example. 3. You can still call the `requestRandomness` function. However, the v2 `requestRandomness` function requires several different parameters. See the [Supported networks](/vrf/v2-5/supported-networks) page to adjust them for your own needs. - The `requestRandomness` function in the wrapper contract requires a new `extraArgs` argument that allows you to add extra arguments related to new VRF features. Use the `nativePayment` argument to enable or disable payment in native tokens. - Additionally, the `requestRandomness` function now returns two arguments instead of one: the request ID and the request price. ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ); (uint256 reqId, uint256 reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` 4. If you're paying for requests with LINK, you can still call the `requestRandomness` function. However, if you're paying with native tokens, call the `requestRandomnessPayInNative` function instead. - Both functions return two arguments instead of one: the request ID and the request price. - Both functions require one additional parameter, `extraArgs`. Use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens: ### LINK ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ); (uint256 reqId, uint256 reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` ### Native tokens ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: true}) ); (uint256 reqId, uint256 reqPrice) = requestRandomnessPayInNative( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` 5. Change `fulfillRandomness` function calls to `fulfillRandomWords`. Update the call to handle the returned `uint256[]` array instead of the single `uint256` variable. ## Migration walkthrough VRF v2.5 currently supports subscriptions and direct funding on all [supported networks](/vrf/v2-5/supported-networks). To migrate, you need to [update your existing smart contract code](#update-your-code) and redeploy your contracts. If using subscriptions, [create and fund a new VRF v2.5 subscription](/vrf/v2-5/subscription/create-manage). For direct funding, deploy the [`DirectFundingConsumer`](/samples/VRF/v2-5/DirectFundingConsumer.sol) example: [Open DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) ### Update your code To modify your existing smart contract code to work with VRF v2.5, complete the following changes: ### Subscription 1. Import the [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) contract and remove the v2 `VRFConsumerBaseV2` import. 2. Import the VRF v2.5 coordinator, [`VRFCoordinatorV2_5`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol), and update any old references to the VRF V2 coordinator in your contract. 3. Add a `VRFConsumerBaseV2Plus` constructor, passing in the LINK token address for the network you're using. 4. Update your `requestRandomWords` function calls to reflect the new request structure for VRF v2.5. Make sure to include the new `extraArgs` part of the `VRFV2PlusClient.RandomWordsRequest` object, and specify whether or not you want to pay for VRF requests using native tokens: ### LINK ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) }) ); ``` ### Native tokens ```solidity uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) }) ); ``` 5. When using the [`@chainlink/contracts`](https://www.npmjs.com/package/@chainlink/contracts/v/1.1.1) package version 1.1.1 and later, update your `fulfillRandomWords` function signature to match the `VRFConsumerBaseV2Plus` contract, which has changed to: ``` function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) ``` In the `@chainlink/contracts` package version 1.1.0 and earlier, the `randomWords` parameter has a `memory` storage location. ### Direct funding 1. Import the [`VRFV2PlusWrapperConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) contract and remove the v2 `VRFV2WrapperConsumerBase` import. 2. Add a `VRFV2PlusWrapperConsumerBase` constructor, passing in the VRF wrapper address for the network you're using. Unlike in V2, you don't have to pass the LINK token address to the constructor. 3. If you're paying for requests with LINK, you can still call the `requestRandomness` function. However, if you're paying with native tokens, call the `requestRandomnessPayInNative` function instead. Both functions require one additional parameter, `extraArgs`. Use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens: ### LINK ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) ); (uint256 reqId, uint256 reqPrice) = requestRandomness( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` ### Native tokens ```solidity bytes memory extraArgs = VRFV2PlusClient._argsToBytes( VRFV2PlusClient.ExtraArgsV1({nativePayment: true}) ); (uint256 reqId, uint256 reqPrice) = requestRandomnessPayInNative( callbackGasLimit, requestConfirmations, numWords, extraArgs ); ``` 4. The V2.5 `requestRandomness` and `requestRandomnessPayInNative` functions both return a tuple: `(uint256 requestId, uint256 requestPrice)`. Adjust your `requestRandomWords` function or any other functions in your code where you call the V2.5 wrapper's `requestRandomness` or `requestRandomnessPayInNative` functions. 5. Make sure your contract has a withdraw function for both native tokens and LINK. Both are included in the [direct funding example code](#view-example-code) and the [`VRFV2PlusWrapperConsumerExample`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol) contract. ## View example code View example code for both VRF 2.5 subscription and direct funding: Open the full example `SubscriptionConsumer` contract: [Open SubscriptionConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionConsumer.sol) Open the full example `DirectFundingConsumer` contract: [Open DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) --- # Supported Networks Source: https://docs.chain.link/vrf/v2-5/supported-networks Chainlink VRF allows you to integrate provably fair and verifiably random data in your smart contract. For implementation details, read [Introduction to Chainlink VRF](/vrf). VRF v2.5 coordinators for subscription funding are available on several networks. To use Chainlink VRF on certain networks, you may need to conduct token transfers. You can transfer tokens by using [Chainlink CCIP](/ccip/tutorials/evm/transfer-tokens-from-contract), [Transporter](https://www.transporter.io/) or third-party applications such as [XSwap](https://xswap.link/). > **NOTE: Interfaces and Applications** > > Chainlink CCIP is a messaging protocol. Third parties may build user interfaces or other applications on top of CCIP. > Neither Chainlink Labs nor the Chainlink Foundation owns, controls, endorses, or assumes any responsibility for any > such interfaces or applications. You are solely responsible for your use of such interfaces or applications. Please > visit the Chainlink Foundation [Terms of Service](https://chain.link/terms) for more information. > **CAUTION: Understand Risks associated with Bridges** > > If you are using a cross-chain bridge to transfer your LINK tokens, read the [Bridges and Associated Risks](/resources/bridge-risks) guide to understand what cross-chain bridges are and the risks associated with using them. ## Coordinator parameters These parameters are configured in the coordinator contract. You can view these values by running `getConfig` on the coordinator or by viewing the coordinator contracts in a blockchain explorer. - `uint16 minimumRequestConfirmations`: The minimum number of confirmation blocks on VRF requests before oracles respond - `uint32 maxGasLimit`: The maximum gas limit supported for a `fulfillRandomWords` callback. - `uint32 stalenessSeconds`: How long the coordinator waits until we consider the ETH/LINK price used for converting gas costs to LINK is stale and use `fallbackWeiPerUnitLink` - `uint32 gasAfterPaymentCalculation`: How much gas is used outside of the payment calculation. This covers the additional operations required to decrement the subscription balance and increment the balance for the oracle that handled the request. ## Arbitrum ### Arbitrum Mainnet ### Subscription | Item | Value | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xf97f4df75117a78c1A5a0DBb814Af92458539FB4](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) | | VRF Coordinator | [0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e](https://arbiscan.io/address/0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e) | | 2 gwei Key Hash | 0x9e9e46732b32662b9adc6f3abdf6c5e926a666d174a4d6b8e39c4cca76a38897 | | 30 gwei Key Hash | 0x8472ba59cf7134dfe321f4d61a430c4857e8b19cdd5230b09952a92671c24409 | | 150 gwei Key Hash | 0xe9f223d7d83ec85c4f78042a4845af3a1c8df7757b4997b815ce4b8d07aca68c | | Premium percentage (paying with ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0xf97f4df75117a78c1A5a0DBb814Af92458539FB4](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) | | | VRF Wrapper | [0x14632CD5c12eC5875D41350B55e825c54406BaaB](https://arbiscan.io/address/0x14632CD5c12eC5875D41350B55e825c54406BaaB) | | | VRF Coordinator | [0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e](https://arbiscan.io/address/0x3C0Ca683b403E37668AE3DC4FB62F4B29B6f7a3e) | | | 2 gwei Key Hash | 0x9e9e46732b32662b9adc6f3abdf6c5e926a666d174a4d6b8e39c4cca76a38897 | | | 30 gwei Key Hash | 0x8472ba59cf7134dfe321f4d61a430c4857e8b19cdd5230b09952a92671c24409 | | | 150 gwei Key Hash | 0xe9f223d7d83ec85c4f78042a4845af3a1c8df7757b4997b815ce4b8d07aca68c | | | Premium percentage (paying with ETH) | 60 | | | Premium percentage (paying with LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 104500 | | | Coordinator Gas Overhead (LINK) | 126500 | | | Coordinator Gas Overhead per Word | 435 | | ### Arbitrum Sepolia Testnet Testnet ETH and LINK are available from [https://faucets.chain.link/arbitrum-sepolia](https://faucets.chain.link/arbitrum-sepolia) ### Subscription | Item | Value | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xb1D4538B4571d411F07960EF2838Ce337FE1E80E](https://sepolia.arbiscan.io/address/0xb1D4538B4571d411F07960EF2838Ce337FE1E80E) | | VRF Coordinator | [0x5CE8D5A2BC84beb22a398CCA51996F7930313D61](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) | | 50 gwei Key Hash | 0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be | | Premium percentage (paying with Sepolia ETH) | 60 | | Premium percentage (paying with testnet LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0xb1D4538B4571d411F07960EF2838Ce337FE1E80E](https://sepolia.arbiscan.io/address/0xb1D4538B4571d411F07960EF2838Ce337FE1E80E) | | | VRF Wrapper | [0x29576aB8152A09b9DC634804e4aDE73dA1f3a3CC](https://sepolia.arbiscan.io/address/0x29576aB8152A09b9DC634804e4aDE73dA1f3a3CC) | | | VRF Coordinator | [0x5CE8D5A2BC84beb22a398CCA51996F7930313D61](https://sepolia.arbiscan.io/address/0x5CE8D5A2BC84beb22a398CCA51996F7930313D61) | | | 50 gwei Key Hash | 0x1770bdc7eec7771f7ba4ffd640f34260d7f095b79c92d34a5b2551d6f6cfd2be | | | Premium percentage (paying with Sepolia ETH) | 60 | | | Premium percentage (paying with testnet LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 104500 | | | Coordinator Gas Overhead (LINK) | 126500 | | | Coordinator Gas Overhead per Word | 435 | | ## Avalanche ### Avalanche Mainnet ### Subscription | Item | Value | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x5947BB275c521040051D82396192181b413227A3](https://snowtrace.io/address/0x5947BB275c521040051D82396192181b413227A3) | | VRF Coordinator | [0xE40895D055bccd2053dD0638C9695E326152b1A4](https://snowtrace.io/address/0xE40895D055bccd2053dD0638C9695E326152b1A4) | | 200 gwei Key Hash | 0xea7f56be19583eeb8255aa79f16d8bd8a64cedf68e42fefee1c9ac5372b1a102 | | 500 gwei Key Hash | 0x84213dcadf1f89e4097eb654e3f284d7d5d5bda2bd4748d8b7fada5b3a6eaa0d | | 1000 gwei Key Hash | 0xe227ebd10a873dde8e58841197a07b410038e405f1180bd117be6f6557fa491c | | Premium percentage (paying with AVAX) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x5947BB275c521040051D82396192181b413227A3](https://snowtrace.io/address/0x5947BB275c521040051D82396192181b413227A3) | | | VRF Wrapper | [0x62Fb87c10A917580cA99AB9a86E213Eb98aa820C](https://snowtrace.io/address/0x62Fb87c10A917580cA99AB9a86E213Eb98aa820C) | | | VRF Coordinator | [0xE40895D055bccd2053dD0638C9695E326152b1A4](https://snowtrace.io/address/0xE40895D055bccd2053dD0638C9695E326152b1A4) | | | 200 gwei Key Hash | 0xea7f56be19583eeb8255aa79f16d8bd8a64cedf68e42fefee1c9ac5372b1a102 | | | 500 gwei Key Hash | 0x84213dcadf1f89e4097eb654e3f284d7d5d5bda2bd4748d8b7fada5b3a6eaa0d | | | 1000 gwei Key Hash | 0xe227ebd10a873dde8e58841197a07b410038e405f1180bd117be6f6557fa491c | | | Premium percentage (paying with AVAX) | 60 | | | Premium percentage (paying with LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 107000 | | | Coordinator Gas Overhead (LINK) | 129000 | | | Coordinator Gas Overhead per Word | 435 | | ### Avalanche Fuji Testnet Testnet LINK is available from [https://faucets.chain.link/fuji](https://faucets.chain.link/fuji) ### Subscription | Item | Value | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846](https://testnet.snowtrace.io/address/0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846) | | VRF Coordinator | [0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE](https://testnet.snowtrace.io/address/0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE) | | 300 gwei Key Hash | 0xc799bd1e3bd4d1a41cd4968997a4e03dfd2a3c7c04b695881138580163f42887 | | Premium percentage (paying with testnet AVAX) | 60 | | Premium percentage (paying with testnet LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846](https://testnet.snowtrace.io/address/0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846) | | | VRF Wrapper | [0x327B83F409E1D5f13985c6d0584420FA648f1F56](https://testnet.snowtrace.io/address/0x327B83F409E1D5f13985c6d0584420FA648f1F56) | | | VRF Coordinator | [0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE](https://testnet.snowtrace.io/address/0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE) | | | 300 gwei Key Hash | 0xc799bd1e3bd4d1a41cd4968997a4e03dfd2a3c7c04b695881138580163f42887 | | | Premium percentage (paying with testnet AVAX) | 60 | | | Premium percentage (paying with testnet LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 104500 | | | Coordinator Gas Overhead (LINK) | 126500 | | | Coordinator Gas Overhead per Word | 435 | | ## BASE ### BASE Mainnet ### Subscription | Item | Value | | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196](https://basescan.org/address/0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196) | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://basescan.org/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | 2 gwei Key Hash | 0x00b81b5a830cb0a4009fbd8904de511e28631e62ce5ad231373d3cdad373ccab | | 30 gwei Key Hash | 0xdc2f87677b01473c763cb0aee938ed3341512f6057324a584e5944e786144d70 | | Premium percentage (paying with BASE Mainnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196](https://basescan.org/address/0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196) | | | VRF Wrapper | [0xb0407dbe851f8318bd31404A49e658143C982F23](https://basescan.org/address/0xb0407dbe851f8318bd31404A49e658143C982F23) | | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://basescan.org/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | | 2 gwei Key Hash | 0x00b81b5a830cb0a4009fbd8904de511e28631e62ce5ad231373d3cdad373ccab | | | 30 gwei Key Hash | 0xdc2f87677b01473c763cb0aee938ed3341512f6057324a584e5944e786144d70 | | | Premium percentage (paying with BASE Mainnet ETH) | 60 | | | Premium percentage (paying with LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 128500 | | | Coordinator Gas Overhead (LINK) | 150400 | | | Coordinator Gas Overhead per Word | 435 | | ### BASE Sepolia Testnet ### Subscription | Item | Value | | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xE4aB69C077896252FAFBD49EFD26B5D171A32410](https://sepolia.basescan.org/address/0xE4aB69C077896252FAFBD49EFD26B5D171A32410) | | VRF Coordinator | [0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE](https://sepolia.basescan.org/address/0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE) | | 30 gwei Key Hash | 0x9e1344a1247c8a1785d0a4681a27152bffdb43666ae5bf7d14d24a5efd44bf71 | | Premium percentage (paying with Sepolia BASE ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0xE4aB69C077896252FAFBD49EFD26B5D171A32410](https://sepolia.basescan.org/address/0xE4aB69C077896252FAFBD49EFD26B5D171A32410) | | | VRF Wrapper | [0x7a1BaC17Ccc5b313516C5E16fb24f7659aA5ebed](https://sepolia.basescan.org/address/0x7a1BaC17Ccc5b313516C5E16fb24f7659aA5ebed) | | | VRF Coordinator | [0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE](https://sepolia.basescan.org/address/0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE) | | | 30 gwei Key Hash | 0x9e1344a1247c8a1785d0a4681a27152bffdb43666ae5bf7d14d24a5efd44bf71 | | | Premium percentage (paying with Sepolia BASE ETH) | 60 | | | Premium percentage (paying with LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 128500 | | | Coordinator Gas Overhead (LINK) | 150400 | | | Coordinator Gas Overhead per Word | 435 | | ## BNB Chain ### BNB Chain Mainnet The LINK provided by the [BNB Chain Bridge](https://www.bnbchain.world/en/bridge) is not ERC-677 compatible, so cannot be used with Chainlink oracles. However, it can be [**converted to the official LINK token on BNB Chain using Chainlink's PegSwap service**](https://pegswap.chain.link/). ### Subscription | Item | Value | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x404460C6A5EdE2D891e8297795264fDe62ADBB75](https://bscscan.com/token/0x404460C6A5EdE2D891e8297795264fDe62ADBB75) | | VRF Coordinator | [0xd691f04bc0C9a24Edb78af9E005Cf85768F694C9](https://bscscan.com/address/0xd691f04bc0C9a24Edb78af9E005Cf85768F694C9) | | 200 gwei Key Hash | 0x130dba50ad435d4ecc214aad0d5820474137bd68e7e77724144f27c3c377d3d4 | | 500 gwei Key Hash | 0xeb0f72532fed5c94b4caf7b49caf454b35a729608a441101b9269efb7efe2c6c | | 1000 gwei Key Hash | 0xb94a4fdb12830e15846df59b27d7c5d92c9c24c10cf6ae49655681ba560848dd | | Premium percentage (paying with BNB) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x404460C6A5EdE2D891e8297795264fDe62ADBB75](https://bscscan.com/token/0x404460C6A5EdE2D891e8297795264fDe62ADBB75) | | VRF Wrapper | [0x471506e6ADED0b9811D05B8cAc8Db25eE839Ac94](https://bscscan.com/address/0x471506e6ADED0b9811D05B8cAc8Db25eE839Ac94) | | VRF Coordinator | [0xd691f04bc0C9a24Edb78af9E005Cf85768F694C9](https://bscscan.com/address/0xd691f04bc0C9a24Edb78af9E005Cf85768F694C9) | | 200 gwei Key Hash | 0x130dba50ad435d4ecc214aad0d5820474137bd68e7e77724144f27c3c377d3d4 | | 500 gwei Key Hash | 0xeb0f72532fed5c94b4caf7b49caf454b35a729608a441101b9269efb7efe2c6c | | 1000 gwei Key Hash | 0xb94a4fdb12830e15846df59b27d7c5d92c9c24c10cf6ae49655681ba560848dd | | Premium percentage (paying with testnet BNB) | 60 | | Premium percentage (paying with testnet LINK) | 50 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 99500 | | Coordinator Gas Overhead (LINK) | 121500 | | Coordinator Gas Overhead per Word | 435 | ### BNB Chain Testnet ### Subscription Testnet LINK is available from [https://faucets.chain.link/bnb-chain-testnet](https://faucets.chain.link/bnb-chain-testnet) | Item | Value | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06](https://testnet.bscscan.com/address/0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06) | | VRF Coordinator | [0xDA3b641D438362C440Ac5458c57e00a712b66700](https://testnet.bscscan.com/address/0xDA3b641D438362C440Ac5458c57e00a712b66700) | | 50 gwei Key Hash | 0x8596b430971ac45bdf6088665b9ad8e8630c9d5049ab54b14dff711bee7c0e26 | | Premium percentage (paying with testnet BNB) | 60 | | Premium percentage (paying with testnet LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06](https://testnet.bscscan.com/address/0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06) | | | VRF Wrapper | [0x471506e6ADED0b9811D05B8cAc8Db25eE839Ac94](https://testnet.bscscan.com/address/0x471506e6ADED0b9811D05B8cAc8Db25eE839Ac94) | | | VRF Coordinator | [0xDA3b641D438362C440Ac5458c57e00a712b66700](https://testnet.bscscan.com/address/0xDA3b641D438362C440Ac5458c57e00a712b66700) | | | 50 gwei Key Hash | 0x8596b430971ac45bdf6088665b9ad8e8630c9d5049ab54b14dff711bee7c0e26 | | | Premium percentage (paying with testnet BNB) | 60 | | | Premium percentage (paying with testnet LINK) | 50 | | | Minimum Confirmations | 3 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 99500 | | | Coordinator Gas Overhead (LINK) | 121500 | | | Coordinator Gas Overhead per Word | 435 | | ## Ethereum ### Ethereum Mainnet ### Subscription | Item | Value | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x514910771AF9Ca656af840dff83E8264EcF986CA](https://etherscan.io/token/0x514910771AF9Ca656af840dff83E8264EcF986CA) | | VRF Coordinator | [0xD7f86b4b8Cae7D942340FF628F82735b7a20893a](https://etherscan.io/address/0xD7f86b4b8Cae7D942340FF628F82735b7a20893a) | | 200 gwei Key Hash | 0x8077df514608a09f83e4e8d300645594e5d7234665448ba83f51a50f842bd3d9 | | 500 gwei Key Hash | 0x3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b | | 1000 gwei Key Hash | 0xc6bf2e7b88e5cfbb4946ff23af846494ae1f3c65270b79ee7876c9aa99d3d45f | | Premium percentage (paying with ETH) | 24 | | Premium percentage (paying with LINK) | 20 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x514910771AF9Ca656af840dff83E8264EcF986CA](https://etherscan.io/token/0x514910771AF9Ca656af840dff83E8264EcF986CA) | | VRF Wrapper | [0x02aae1A04f9828517b3007f83f6181900CaD910c](https://etherscan.io/address/0x02aae1A04f9828517b3007f83f6181900CaD910c) | | VRF Coordinator | [0xD7f86b4b8Cae7D942340FF628F82735b7a20893a](https://etherscan.io/address/0xD7f86b4b8Cae7D942340FF628F82735b7a20893a) | | 200 gwei Key Hash | 0x8077df514608a09f83e4e8d300645594e5d7234665448ba83f51a50f842bd3d9 | | 500 gwei Key Hash | 0x3fd2fec10d06ee8f65e7f2e95f5c56511359ece3f33960ad8a866ae24a8ff10b | | 1000 gwei Key Hash | 0xc6bf2e7b88e5cfbb4946ff23af846494ae1f3c65270b79ee7876c9aa99d3d45f | | Premium percentage (paying with ETH) | 24 | | Premium percentage (paying with LINK) | 20 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 90000 | | Coordinator Gas Overhead (LINK) | 112000 | | Coordinator Gas Overhead per Word | 435 | ### Ethereum Sepolia Testnet Testnet LINK and ETH are available from [faucets.chain.link](https://faucets.chain.link/sepolia). Testnet ETH is also available from several public [ETH faucets](https://faucetlink.to/sepolia). ### Subscription | Item | Value | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x779877A7B0D9E8603169DdbD7836e478b4624789](https://sepolia.etherscan.io/token/0x779877A7B0D9E8603169DdbD7836e478b4624789) | | VRF Coordinator | [0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B](https://sepolia.etherscan.io/address/0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) | | 500 gwei Key Hash | 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae | | Premium percentage (paying with Sepolia ETH) | 24 | | Premium percentage (paying with testnet LINK) | 20 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x779877A7B0D9E8603169DdbD7836e478b4624789](https://sepolia.etherscan.io/token/0x779877A7B0D9E8603169DdbD7836e478b4624789) | | VRF Wrapper | [0x195f15F2d49d693cE265b4fB0fdDbE15b1850Cc1](https://sepolia.etherscan.io/address/0x195f15F2d49d693cE265b4fB0fdDbE15b1850Cc1) | | VRF Coordinator | [0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B](https://sepolia.etherscan.io/address/0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) | | 500 gwei Key Hash | 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae | | Premium percentage (paying with Sepolia ETH) | 24 | | Premium percentage (paying with testnet LINK) | 20 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 90000 | | Coordinator Gas Overhead (LINK) | 112000 | | Coordinator Gas Overhead per Word | 435 | ## OP ### OP Mainnet ### Subscription | Item | Value | | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6](https://optimistic.etherscan.io/address/0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6) | | VRF Coordinator | [0x5FE58960F730153eb5A84a47C51BD4E58302E1c8](https://optimistic.etherscan.io/address/0x5FE58960F730153eb5A84a47C51BD4E58302E1c8) | | 2 gwei Key Hash | 0xa16a2316f92fa0abfd0029eea74e947d0613728e934d9794cd78bc02e2f69de4 | | 30 gwei Key Hash | 0x8e7a847ba0757d1c302a3f0fde7b868ef8cf4acc32e48505f1a1d53693a10a19 | | Premium percentage (paying with OP Mainnet) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6](https://optimistic.etherscan.io/address/0x350a791bfc2c21f9ed5d10980dad2e2638ffa7f6) | | | VRF Wrapper | [0x6A39cE9604FAD060B32bc35BE2e0D3825B2b8D4B](https://optimistic.etherscan.io/address/0x6A39cE9604FAD060B32bc35BE2e0D3825B2b8D4B) | | | VRF Coordinator | [0x5FE58960F730153eb5A84a47C51BD4E58302E1c8](https://optimistic.etherscan.io/address/0x5FE58960F730153eb5A84a47C51BD4E58302E1c8) | | | 2 gwei Key Hash | 0xa16a2316f92fa0abfd0029eea74e947d0613728e934d9794cd78bc02e2f69de4 | | | 30 gwei Key Hash | 0x8e7a847ba0757d1c302a3f0fde7b868ef8cf4acc32e48505f1a1d53693a10a19 | | | Premium percentage (paying with OP Mainnet) | 60 | | | Premium percentage (paying with LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 128500 | | | Coordinator Gas Overhead (LINK) | 150400 | | | Coordinator Gas Overhead per Word | 435 | | ### OP Sepolia Testnet ### Subscription | Item | Value | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xE4aB69C077896252FAFBD49EFD26B5D171A32410](https://sepolia-optimism.etherscan.io/token/0xE4aB69C077896252FAFBD49EFD26B5D171A32410) | | VRF Coordinator | [0x02667f44a6a44E4BDddCF80e724512Ad3426B17d](https://sepolia-optimism.etherscan.io/address/0x02667f44a6a44E4BDddCF80e724512Ad3426B17d) | | 30 gwei Key Hash | 0xc3d5bc4d5600fa71f7a50b9ad841f14f24f9ca4236fd00bdb5fda56b052b28a4 | | Premium percentage (paying with OP Sepolia ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0xE4aB69C077896252FAFBD49EFD26B5D171A32410](https://sepolia-optimism.etherscan.io/token/0xE4aB69C077896252FAFBD49EFD26B5D171A32410) | | | VRF Wrapper | [0xA8A278BF534BCa72eFd6e6C9ac573E98c21A6171](https://sepolia-optimism.etherscan.io/address/0xA8A278BF534BCa72eFd6e6C9ac573E98c21A6171) | | | VRF Coordinator | [0x02667f44a6a44E4BDddCF80e724512Ad3426B17d](https://sepolia-optimism.etherscan.io/address/0x02667f44a6a44E4BDddCF80e724512Ad3426B17d) | | | 30 gwei Key Hash | 0xc3d5bc4d5600fa71f7a50b9ad841f14f24f9ca4236fd00bdb5fda56b052b28a4 | | | Premium percentage (paying with OP Sepolia ETH) | 60 | | | Premium percentage (paying with testnet LINK) | 50 | | | Minimum Confirmations | 0 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 128500 | | | Coordinator Gas Overhead (LINK) | 150400 | | | Coordinator Gas Overhead per Word | 435 | | ## Polygon ### Polygon Mainnet The LINK provided by the [Polygon Bridge](https://wallet.polygon.technology/polygon/bridge) is not ERC-677 compatible, so cannot be used with Chainlink oracles. However, it can be [**converted to the official LINK token on Polygon using Chainlink's PegSwap service**](https://pegswap.chain.link/) ### Subscription | Item | Value | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | LINK Token | [0xb0897686c545045aFc77CF20eC7A532E3120E0F1](https://polygonscan.com/address/0xb0897686c545045aFc77CF20eC7A532E3120E0F1) | | VRF Coordinator | [0xec0Ed46f36576541C75739E915ADbCb3DE24bD77](https://polygonscan.com/address/0xec0Ed46f36576541C75739E915ADbCb3DE24bD77) | | 200 gwei Key Hash | 0x0ffbbd0c1c18c0263dd778dadd1d64240d7bc338d95fec1cf0473928ca7eaf9e | | 500 gwei Key Hash | 0x719ed7d7664abc3001c18aac8130a2265e1e70b7e036ae20f3ca8b92b3154d86 | | 1000 gwei Key Hash | 0x192234a5cda4cc07c0b66dfbcfbb785341cc790edc50032e842667dbb506cada | | Premium percentage (paying with POL) | 84 | | Premium percentage (paying with LINK) | 70 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | - | | LINK Token | [0xb0897686c545045aFc77CF20eC7A532E3120E0F1](https://polygonscan.com/address/0xb0897686c545045aFc77CF20eC7A532E3120E0F1) | | | VRF Wrapper | [0xc8F13422c49909F4Ec24BF65EDFBEbe410BB9D7c](https://polygonscan.com/address/0xc8F13422c49909F4Ec24BF65EDFBEbe410BB9D7c) | | | VRF Coordinator | [0xec0Ed46f36576541C75739E915ADbCb3DE24bD77](https://polygonscan.com/address/0xec0Ed46f36576541C75739E915ADbCb3DE24bD77) | | | 200 gwei Key Hash | 0x0ffbbd0c1c18c0263dd778dadd1d64240d7bc338d95fec1cf0473928ca7eaf9e | | | 500 gwei Key Hash | 0x719ed7d7664abc3001c18aac8130a2265e1e70b7e036ae20f3ca8b92b3154d86 | | | 1000 gwei Key Hash | 0x192234a5cda4cc07c0b66dfbcfbb785341cc790edc50032e842667dbb506cada | | | Premium percentage (paying with POL) | 84 | | | Premium percentage (paying with LINK) | 70 | | | Minimum Confirmations | 3 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 99500 | | | Coordinator Gas Overhead (LINK) | 121500 | | | Coordinator Gas Overhead per Word | 435 | | ### Polygon Amoy Testnet ### Subscription | Item | Value | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904](https://amoy.polygonscan.com/address/0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904) | | VRF Coordinator | [0x343300b5d84D444B2ADc9116FEF1bED02BE49Cf2](https://amoy.polygonscan.com/address/0x343300b5d84D444B2ADc9116FEF1bED02BE49Cf2) | | 500 gwei Key Hash | 0x816bedba8a50b294e5cbd47842baf240c2385f2eaf719edbd4f250a137a8c899 | | Premium percentage (paying with testnet POL) | 84 | | Premium percentage (paying with testnet LINK) | 70 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | - | | LINK Token | [0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904](https://amoy.polygonscan.com/address/0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904) | | | VRF Wrapper | [0x6e6c366a1cd1F92ba87Fd6f96F743B0e6c967Bf0](https://amoy.polygonscan.com/address/0x6e6c366a1cd1F92ba87Fd6f96F743B0e6c967Bf0) | | | VRF Coordinator | [0x343300b5d84D444B2ADc9116FEF1bED02BE49Cf2](https://amoy.polygonscan.com/address/0x343300b5d84D444B2ADc9116FEF1bED02BE49Cf2) | | | 500 gwei Key Hash | 0x816bedba8a50b294e5cbd47842baf240c2385f2eaf719edbd4f250a137a8c899 | | | Premium percentage (paying with testnet POL) | 84 | | | Premium percentage (paying with testnet LINK) | 70 | | | Minimum Confirmations | 3 | | | Maximum Confirmations | 200 | | | Maximum Random Values | 10 | | | Wrapper Gas overhead | 13400 | | | Coordinator Gas Overhead (Native) | 99500 | | | Coordinator Gas Overhead (LINK) | 121500 | | | Coordinator Gas Overhead per Word | 435 | | ## Ronin ### Ronin Mainnet ### Subscription | Item | Value | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b](https://app.roninchain.com/address/0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b) | | VRF Coordinator | [0xa18FD3db9B869AD2A8c55267e0D54dbf6ECEbEda](https://app.roninchain.com/address/0xa18FD3db9B869AD2A8c55267e0D54dbf6ECEbEda) | | 50 gwei Key Hash | 0x1aefc70f3533a251306d6b85a6b336ba0ae2e384226274b236f42c3d5366dbbd | | 200 gwei Key Hash | 0x01753ec79fbf37f6332977d62f25c6d701b11bac255d7e79674fd2886622b0cc | | 1000 gwei Key Hash | 0xdb64d2a17ee501f6c6a8c090e058dfa39ea79d5fd121185bb903f5a69b8038a3 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b](https://app.roninchain.com/address/0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b) | | VRF Wrapper | [0x3B7d0d0CeC08eBF8dad58aCCa4719791378b2329](https://app.roninchain.com/address/0x3B7d0d0CeC08eBF8dad58aCCa4719791378b2329) | | VRF Coordinator | [0xa18FD3db9B869AD2A8c55267e0D54dbf6ECEbEda](https://app.roninchain.com/address/0xa18FD3db9B869AD2A8c55267e0D54dbf6ECEbEda) | | 50 gwei Key Hash | 0x1aefc70f3533a251306d6b85a6b336ba0ae2e384226274b236f42c3d5366dbbd | | 200 gwei Key Hash | 0x01753ec79fbf37f6332977d62f25c6d701b11bac255d7e79674fd2886622b0cc | | 1000 gwei Key Hash | 0xdb64d2a17ee501f6c6a8c090e058dfa39ea79d5fd121185bb903f5a69b8038a3 | | Premium percentage (paying with ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 99500 | | Coordinator Gas Overhead (LINK) | 121500 | | Coordinator Gas Overhead per Word | 435 | ### Ronin Saigon Testnet ### Subscription | Item | Value | | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15](https://saigon-app.roninchain.com/address/0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15) | | VRF Coordinator | [0xc052324E6A27D0E4b2CbF0FdFFBCb3796ea8f8B8](https://saigon-app.roninchain.com/address/0xc052324E6A27D0E4b2CbF0FdFFBCb3796ea8f8B8) | | 200 gwei Key Hash | 0x0a79a60cc054d8da06a5050a1d07f0fec08088ca64192cf67477f8cc3e549f71 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15](https://saigon-app.roninchain.com/address/0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15) | | VRF Wrapper | [0x4664273cf5Eb350c864c2F37F63b045a883F93C6](https://saigon-app.roninchain.com/address/0x4664273cf5Eb350c864c2F37F63b045a883F93C6) | | VRF Coordinator | [0xc052324E6A27D0E4b2CbF0FdFFBCb3796ea8f8B8](https://saigon-app.roninchain.com/address/0xc052324E6A27D0E4b2CbF0FdFFBCb3796ea8f8B8) | | 200 gwei Key Hash | 0x0a79a60cc054d8da06a5050a1d07f0fec08088ca64192cf67477f8cc3e549f71 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 99500 | | Coordinator Gas Overhead (LINK) | 121500 | | Coordinator Gas Overhead per Word | 435 | ## Soneium ### Soneium Mainnet ### Subscription | Item | Value | | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec](https://soneium.blockscout.com/address/0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec) | | VRF Coordinator | [0xb89BB0aB64b219Ba7702f862020d879786a2BC49](https://soneium.blockscout.com/address/0xb89BB0aB64b219Ba7702f862020d879786a2BC49) | | 2 gwei Key Hash | 0x508b86c17b9abbdef2b903bd4f1b03ae321d7c1431b9ccac97d5927b4619e050 | | 30 gwei Key Hash | 0x7611210a5ac0abd39b581bd4ce1108aa0b9e63994daa32cc7302d98ed47747c1 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec](https://soneium.blockscout.com/address/0x32D8F819C8080ae44375F8d383Ffd39FC642f3Ec) | | VRF Wrapper | [0x656155C8bD09d1741385C525010590522758345c](https://soneium.blockscout.com/address/0x656155C8bD09d1741385C525010590522758345c) | | VRF Coordinator | [0xb89BB0aB64b219Ba7702f862020d879786a2BC49](https://soneium.blockscout.com/address/0xb89BB0aB64b219Ba7702f862020d879786a2BC49) | | 2 gwei Key Hash | 0x508b86c17b9abbdef2b903bd4f1b03ae321d7c1431b9ccac97d5927b4619e050 | | 30 gwei Key Hash | 0x7611210a5ac0abd39b581bd4ce1108aa0b9e63994daa32cc7302d98ed47747c1 | | Premium percentage (paying with ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 128500 | | Coordinator Gas Overhead (LINK) | 150400 | | Coordinator Gas Overhead per Word | 435 | ### Soneium Minato Testnet ### Subscription | Item | Value | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2](https://soneium-minato.blockscout.com/address/0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2) | | VRF Coordinator | [0x3Fa01AB73beB4EA09e78FC0849FCe31d0b035b47](https://soneium-minato.blockscout.com/address/0x3Fa01AB73beB4EA09e78FC0849FCe31d0b035b47) | | 30 gwei Key Hash | 0x0c970a50393bea0011d5cec18c15c80c6deb37888b9ff579f476b3e52f6d3922 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Direct funding | Item | Value | | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2](https://soneium-minato.blockscout.com/address/0x7ea13478Ea3961A0e8b538cb05a9DF0477c79Cd2) | | VRF Wrapper | [0xB64019F234f2A4951261B111C6B43eb0d8f33b76](https://soneium-minato.blockscout.com/address/0xB64019F234f2A4951261B111C6B43eb0d8f33b76) | | VRF Coordinator | [0x3Fa01AB73beB4EA09e78FC0849FCe31d0b035b47](https://soneium-minato.blockscout.com/address/0x3Fa01AB73beB4EA09e78FC0849FCe31d0b035b47) | | 30 gwei Key Hash | 0x0c970a50393bea0011d5cec18c15c80c6deb37888b9ff579f476b3e52f6d3922 | | Premium percentage (paying with testnet ETH) | 60 | | Premium percentage (paying with LINK) | 50 | | Minimum Confirmations | 0 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 13400 | | Coordinator Gas Overhead (Native) | 128500 | | Coordinator Gas Overhead (LINK) | 150400 | | Coordinator Gas Overhead per Word | 435 | --- # VRF Security Considerations Source: https://docs.chain.link/vrf/v2-5/security Gaining access to high quality randomness onchain requires a solution like Chainlink's VRF, but it also requires you to understand some of the ways that miners or validators can potentially manipulate randomness generation. Here are some of the top security considerations you should review in your project. ## Use `requestId` to match randomness requests with their fulfillment in order If your contract could have multiple VRF requests in flight simultaneously, you must ensure that the order in which the VRF fulfillments arrive cannot be used to manipulate your contract's user-significant behavior. Blockchain miners/validators can control the order in which your requests appear onchain, and hence the order in which your contract responds to them. For example, if you made randomness requests `A`, `B`, `C` in short succession, there is no guarantee that the associated randomness fulfillments will also be in order `A`, `B`, `C`. The randomness fulfillments might just as well arrive at your contract in order `C`, `A`, `B` or any other order. We recommend using the `requestID` to match randomness requests with their corresponding fulfillments. ## Choose a safe block confirmation time, which will vary between blockchains In principle, miners/validators of your underlying blockchain could rewrite the chain's history to put a randomness request from your contract into a different block, which would result in a different VRF output. Note that this does not enable a miner to determine the random value in advance. It only enables them to get a fresh random value that might or might not be to their advantage. By way of analogy, they can only re-roll the dice, not predetermine or predict which side it will land on. You must choose an appropriate confirmation time for the randomness requests you make. Confirmation time is how many blocks the VRF service waits before writing a fulfillment to the chain to make potential rewrite attacks unprofitable in the context of your application and its value-at-risk. ## Do not allow re-requesting or cancellation of randomness Any re-request or cancellation of randomness is an incorrect use of VRF v2.5. dApps that implement the ability to cancel or re-request randomness for specific commitments must consider the additional attack vectors created by this capability. For example, you must prevent the ability for any party to discard unfavorable randomness. ## Don't accept bids/bets/inputs after you have made a randomness request Consider the example of a contract that mints a random NFT in response to a user's actions. The contract should: 1. Record whatever actions of the user may affect the generated NFT. 2. **Stop accepting further user actions that might affect the generated NFT** and issue a randomness request. 3. On randomness fulfillment, mint the NFT. Generally speaking, whenever an outcome in your contract depends on some user-supplied inputs and randomness, the contract should not accept any additional user-supplied inputs after it submits the randomness request. Otherwise, the cryptoeconomic security properties may be violated by an attacker that can rewrite the chain. ## `fulfillRandomWords` must not revert If your `fulfillRandomWords()` implementation reverts, the VRF service will not attempt to call it a second time. Make sure your contract logic does not revert. Consider simply storing the randomness and taking more complex follow-on actions in separate contract calls made by you, your users, or an [Automation Node](/chainlink-automation). ## Use `VRFConsumerBaseV2Plus` in your contract, to interact with the VRF service If you implement the [subscription method](/vrf/v2-5/overview/subscription), use `VRFConsumerBaseV2Plus`. It includes a check to ensure the randomness is fulfilled by `VRFCoordinatorV2_5`. For this reason, it is a best practice to inherit from `VRFConsumerBaseV2Plus`. Similarly, don't override `rawFulfillRandomness`. ## Avoid ERC-4337 account-abstracted (smart-account) wallets for subscription management Pre-signed ERC-4337 UserOperations can be executed by any bundler until they expire. If executed inside a fulfillment transaction callback, the subscription management call can no-op, delaying or preventing the change. ## Keep your subscription funded well above the minimum balance Fulfillments require sufficient subscription balance at processing time. If the balance sits near the minimum and multiple consumers make concurrent requests, fulfillments can be delayed. After adding funds, it can take some time for previous requests to be processed again. --- # VRF Best Practices Source: https://docs.chain.link/vrf/v2-5/best-practices These are example best practices for using Chainlink VRF. To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Getting a random number within a range If you need to generate a random number within a given range, use [modulo](https://docs.soliditylang.org/en/v0.8.7/types.html#modulo) to define the limits of your range. Below you can see how to get a random number in a range from 1 to 50. ```solidity function fulfillRandomWords( uint256, /* requestId */ uint256[] memory randomWords ) internal override { // Assuming only one random word was requested. s_randomRange = (randomWords[0] % 50) + 1; } ``` ## Getting multiple random values If you want to get multiple random values from a single VRF request, you can request this directly with the `numWords` argument: - If you are using the VRF v2.5 subscription method, see the [full example code](/vrf/v2-5/migration-from-v2#compare-example-code) for an example where one request returns multiple random values. ## Processing simultaneous VRF requests If you want to have multiple VRF requests processing simultaneously, create a mapping between `requestId` and the response. You might also create a mapping between the `requestId` and the address of the requester to track which address made each request. ```solidity mapping(uint256 => uint256[]) public s_requestIdToRandomWords; mapping(uint256 => address) public s_requestIdToAddress; uint256 public s_requestId; function requestRandomWords() external onlyOwner returns (uint256) { uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) // new parameter }) ); s_requestIdToAddress[requestId] = msg.sender; // Store the latest requestId for this example. s_requestId = requestId; // Return the requestId to the requester. return requestId; } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { // You can return the value to the requester, // but this example simply stores it. s_requestIdToRandomWords[requestId] = randomWords; } ``` You could also map the `requestId` to an index to keep track of the order in which a request was made. ```solidity mapping(uint256 => uint256) s_requestIdToRequestIndex; mapping(uint256 => uint256[]) public s_requestIndexToRandomWords; uint256 public requestCounter; function requestRandomWords() external onlyOwner { uint256 requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_vrfSubscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) // new parameter }) ); s_requestIdToRequestIndex[requestId] = requestCounter; requestCounter += 1; } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { uint256 requestNumber = s_requestIdToRequestIndex[requestId]; s_requestIndexToRandomWords[requestNumber] = randomWords; } ``` ## Processing VRF responses through different execution paths If you want to process VRF responses depending on predetermined conditions, you can create an `enum`. When requesting for randomness, map each `requestId` to an enum. This way, you can handle different execution paths in `fulfillRandomWords`. See the following example: ```solidity // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. // It shows how to setup multiple execution paths for handling a response. pragma solidity 0.8.19; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {IVRFCoordinatorV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol"; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract VRFv2MultiplePaths is VRFConsumerBaseV2Plus { // Your subscription ID. uint256 s_subscriptionId; // Sepolia coordinator. For other networks, // see https://docs.chain.link/docs/vrf/v2-5/supported-networks address vrfCoordinatorV2Plus = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2-5/supported-networks bytes32 keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; uint32 callbackGasLimit = 100000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 1 random value in one request. // Cannot exceed VRFCoordinatorV2_5.MAX_NUM_WORDS. uint32 numWords = 1; enum Variable { A, B, C } uint256 public variableA; uint256 public variableB; uint256 public variableC; mapping(uint256 => Variable) public requests; // events event FulfilledA(uint256 requestId, uint256 value); event FulfilledB(uint256 requestId, uint256 value); event FulfilledC(uint256 requestId, uint256 value); constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinatorV2Plus) { s_vrfCoordinator = IVRFCoordinatorV2Plus(vrfCoordinatorV2Plus); s_subscriptionId = subscriptionId; } function updateVariable(uint256 input) public { uint256 requestId = s_vrfCoordinator.requestRandomWords(VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_subscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) }) ); if (input % 2 == 0) { requests[requestId] = Variable.A; } else if (input % 3 == 0) { requests[requestId] = Variable.B; } else { requests[requestId] = Variable.C; } } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { Variable variable = requests[requestId]; if (variable == Variable.A) { fulfillA(requestId, randomWords[0]); } else if (variable == Variable.B) { fulfillB(requestId, randomWords[0]); } else if (variable == Variable.C) { fulfillC(requestId, randomWords[0]); } } function fulfillA(uint256 requestId, uint256 randomWord) private { // execution path A variableA = randomWord; emit FulfilledA(requestId, randomWord); } function fulfillB(uint256 requestId, uint256 randomWord) private { // execution path B variableB = randomWord; emit FulfilledB(requestId, randomWord); } function fulfillC(uint256 requestId, uint256 randomWord) private { // execution path C variableC = randomWord; emit FulfilledC(requestId, randomWord); } } ``` --- # VRF Billing Source: https://docs.chain.link/vrf/v2-5/billing This guide explains how to estimate VRF 2.5 costs for both the subscription and direct funding methods. ## Understanding transaction costs ### Subscription For Chainlink VRF v2.5 to fulfill your requests, you must maintain enough funds in your subscription balance. Gas cost calculation includes the following variables: - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. - **Verification gas:** The amount of gas used to verify randomness onchain. The gas price depends on current network conditions. The callback gas depends on your callback function, and the number of random values in your request. The cost of each request is final only after the transaction is complete, but you define the limits you are willing to spend for the request with the following variables: - **Gas lane:** The maximum gas price you are willing to pay for a request in wei. Define this limit by specifying the appropriate `keyHash` in your request. The limits of each gas lane are important for handling gas price spikes when Chainlink VRF bumps the gas price to fulfill your request quickly. - **Callback gas limit:** Specifies the maximum amount of gas you are willing to spend on the callback request. Define this limit by specifying the `callbackGasLimit` value in your request. ### Direct funding For Chainlink VRF v2.5 to fulfill your requests, you must maintain enough funds in your consuming contract. Gas cost calculation includes the following variables: - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. The callback gas depends on your callback function and the number of random values in your request. Set the **callback gas limit** to specify the maximum amount of gas you are willing to spend on the callback request. - **Number of random values requested:** The number of random values (`numWords`) per request to VRF. - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Coordinator overhead gas:** The amount of gas used to verify randomness onchain. This consists of two components: - **Coordinator overhead gas (Native or LINK):** The coordinator overhead gas has different values depending on whether you're using LINK or native tokens. - **Coordinator overhead gas per word:** The amount of additional gas the coordinator uses per random value ("word") that you request. - **Wrapper overhead gas:** The amount of gas used by the VRF Wrapper contract. Because the consuming contract directly pays for the request, the cost is calculated during the request and not during the callback when the randomness is fulfilled. Test your callback function to learn how to correctly estimate the callback gas limit. - If the gas limit is underestimated, the callback fails and the consuming contract is still charged for the work done to generate the requested random values. - If the gas limit is overestimated, the callback function will be executed but your contract is not refunded for the excess gas amount that you paid. Make sure that your consuming contracts have enough funds in either LINK or native tokens to cover the transaction costs. If the consuming contract doesn't have enough funds, your request will revert. ### Estimate gas costs ### Subscription You need to pre-fund your subscription enough to meet the [minimum subscription balance](/vrf/v2-5/overview/subscription#minimum-subscription-balance) in order to have a buffer against gas volatility. After the request is complete, the final gas cost is recorded based on how much gas is used for the verification and callback. The actual cost of the request is deducted from your subscription balance. The total gas cost in wei for your request uses the following formula: ``` (Gas price * (Verification gas + Callback gas)) = total gas cost ``` If you're paying for VRF in LINK, the total gas cost is converted to LINK using the ETH/LINK data feed. In the unlikely event that the data feed is unavailable, the VRF coordinator uses the `fallbackWeiPerUnitLink` value for the conversion instead. The `fallbackWeiPerUnitLink` value is defined in the [coordinator contract](/vrf/v2-5/supported-networks) for your selected network. ### Direct funding The final gas cost to fulfill randomness is estimated based on how much gas is expected for the verification and callback. The total gas cost in wei uses the following formula: ``` (Gas price * (Coordinator gas overhead + Callback gas limit + Wrapper gas overhead)) = total gas cost ``` The total gas cost is converted to LINK using the ETH/LINK data feed. In the unlikely event that the data feed is unavailable, the VRF Wrapper uses the `fallbackWeiPerUnitLink` value for the conversion instead. The `fallbackWeiPerUnitLink` value is defined in the [VRF v2.5 Wrapper contract](/vrf/v2-5/supported-networks) for your selected network. The maximum allowed `callbackGasLimit` value for your requests is defined in the [Coordinator contract supported networks](/vrf/v2-5/supported-networks) page. Because the VRF v2.5 Wrapper adds gas overheads, your `callbackGasLimit` must not exceed `maxGasLimit - wrapperGasOverhead`. ### Apply premium ### Subscription The premium is charged as a percentage of the overall gas cost. The premium is defined in the [coordinator contract](/vrf/v2-5/supported-networks). Premium percentages are listed there as whole integers. For example, a 20% premium is listed as `20`. ``` (total gas cost) * ((100 + Premium percentage) / 100) = total request cost ``` The total request cost is charged to your subscription balance. Since you have the option to pay for VRF requests either in LINK or the native token for the network you're using, your subscription can have both a LINK balance and a native token balance. The premium is higher when you pay with native tokens than when you pay with LINK. For example, the premium percentage for using Ethereum is 24 if you pay with Ethereum, and 20 if you pay with LINK. ### Direct funding The premium is divided in two parts: - Wrapper premium: This premium is charged as a percentage of the overall gas cost. Premium percentages are listed there as whole integers. For example, a 20% premium is listed as `20`. You can find the percentage for your network in the [Supported networks](/vrf/v2-5/supported-networks) page. - Coordinator premium: A flat fee. This premium is defined in the `fulfillmentFlatFeeLinkPPMTier1` parameter in millionths of LINK. You can find the flat fee of the coordinator for your network in the [Supported networks](/vrf/v2-5/supported-networks) page. ``` (Coordinator premium + (total gas cost) * ((100 + Premium percentage) / 100)) = total request cost ``` The total request cost is charged to your consuming contract. The premium is higher when you pay with native tokens than when you pay with LINK. For example, the premium percentage for using Ethereum is 24 if you pay with Ethereum, and 20 if you pay with LINK. ### Subscription cost examples These are example calculations of a VRF subscription request on Ethereum, shown in both ETH and LINK. The values for other supported networks are available on the [Supported Networks](/vrf/v2-5/supported-networks) page. The examples show how to estimate the following: - The [minimum subscription balance](/vrf/v2-5/overview/subscription#minimum-subscription-balance), which is a higher amount you need to reserve before your request is processed. This provides a buffer in case gas prices go higher when processing the request. The VRF Subscription Manager displays your minimum subscription balance as **Max Cost**. - The actual cost of the request after it is processed, which is lower than the minimum subscription balance. #### Estimate minimum subscription balance These example calculations show an estimated minimum subscription balance for using VRF on Ethereum, shown in both ETH and LINK. The premium is higher when you pay with native tokens than when you pay with LINK. ### Paying in LINK | Parameter | Value | | -------------------- | -------- | | Gas lane | 500 gwei | | Callback gas limit | 100000 | | Max verification gas | 200000 | | Premium percentage | 20 | 1. Calculate the total gas cost, using the maximum possible gas price for the selected gas lane, the estimated maximum verification gas, and the full callback gas limit: | Gas cost calculation | Total gas cost | | --------------------------------------------- | ------------------------- | | Gas price x (Verification gas + Callback gas) | | | 500 gwei x (200000 + 100000) | 150000000 gwei (0.15 ETH) | 2. Apply the premium percentage to get the total maximum cost of a request: | Applying premium percentage | Maximum request cost (ETH) | | -------------------------------------------------------- | -------------------------- | | Total gas cost (ETH) \* ((100 + premium percentage)/100) | | | 0.15 ETH \* ((100 + 20)/100) | 0.18 ETH | 3. Convert the total cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.005 ETH per 1 LINK. | ETH to LINK cost conversion | Maximum request cost (LINK) | | --------------------------- | --------------------------- | | 0.18 ETH / 0.005 ETH/LINK | 36 LINK | For this example request to go through, you need to reserve a minimum subscription balance of 36 LINK, but that does not mean the actual request will cost 36 LINK. Check the **Max Cost** in the Subscription Manager to view the minimum subscription balance for all your contracts. When your request is processed, the actual cost of the request is calculated and deducted from your subscription balance. See [the next section](#estimate-vrf-request-cost) for an example of how to calculate the actual request cost. ### Paying in ETH | Parameter | Value | | -------------------- | -------- | | Gas lane | 500 gwei | | Callback gas limit | 100000 | | Max verification gas | 200000 | | Premium percentage | 24 | 1. Calculate the total gas cost, using the maximum possible gas price for the selected gas lane, the estimated maximum verification gas, and the full callback gas limit: | Gas cost calculation | Total gas cost | | --------------------------------------------- | ------------------------- | | Gas price x (Verification gas + Callback gas) | | | 500 gwei x (200000 + 100000) | 150000000 gwei (0.15 ETH) | 2. Apply the premium percentage to get the total maximum cost of a request: | Applying premium percentage | Maximum request cost (ETH) | | -------------------------------------------------------- | -------------------------- | | Total gas cost (ETH) \* ((100 + premium percentage)/100) | | | 0.15 ETH \* ((100 + 24)/100) | 0.186 ETH | For this example request to go through, you need to reserve a minimum subscription balance of 0.186 ETH, but that does not mean the actual request will cost 0.186 ETH. Check the **Max Cost** in the Subscription Manager to view the minimum subscription balance for all your contracts. When your request is processed, the actual cost of the request is deducted from your subscription balance. See [the next section](#estimate-vrf-request-cost) for an example of how to calculate the actual request cost. #### Estimate VRF request cost These example calculations show a cost breakdown of a VRF subscription request on the Ethereum network. Check [Etherscan](https://etherscan.io/gastracker) for current gas prices. ### Paying in LINK | Parameter | Value | | --------------------- | ------- | | Actual gas price | 50 gwei | | Callback gas used | 95000 | | Verification gas used | 115000 | | Premium percentage | 20 | 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | --------------------------------------------- | -------------------------- | | Gas price x (Verification gas + Callback gas) | | | 50 gwei x (115000 + 95000) | 10500000 gwei (0.0105 ETH) | 2. Apply the premium percentage to get the total cost of a request: | Applying premium percentage | Total request cost (ETH) | | -------------------------------------------------------- | ------------------------ | | Total gas cost (ETH) \* ((100 + premium percentage)/100) | | | 0.0105 ETH \* ((100 + 20)/100) | 0.0126 ETH | 3. Convert the total cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.005 ETH per 1 LINK. | ETH to LINK cost conversion | Total gas cost (LINK) | | --------------------------- | --------------------- | | 0.0126 ETH / 0.005 ETH/LINK | 2.52 LINK | This example request would cost 2.52 LINK, which is deducted from your subscription balance. ### Paying in ETH | Parameter | Value | | --------------------- | ------- | | Actual gas price | 50 gwei | | Callback gas used | 95000 | | Verification gas used | 115000 | | Premium percentage | 24 | 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | --------------------------------------------- | -------------------------- | | Gas price x (Verification gas + Callback gas) | | | 50 gwei x (115000 + 95000) | 10500000 gwei (0.0105 ETH) | 2. Apply the premium percentage to get the total maximum cost of a request: | Applying premium percentage | Maximum request cost (ETH) | | -------------------------------------------------------- | -------------------------- | | Total gas cost (ETH) \* ((100 + premium percentage)/100) | | | 0.0105 ETH \* ((100 + 24)/100) | 0.01302 ETH | This example request would cost 0.01302 ETH, which is deducted from your subscription balance. ### Direct funding cost examples These are example calculations of a VRF direct funding request on Ethereum, shown in both ETH and LINK. The values for other supported networks are available on the [Supported Networks](/vrf/v2-5/supported-networks) page. ### Paying in LINK | Parameter | Value | | --------------------------------- | ------- | | Gas price | 50 gwei | | Callback gas limit | 100000 | | Coordinator gas overhead (LINK) | 112000 | | Wrapper gas overhead | 13400 | | Coordinator gas overhead per word | 435 | | Number of random values (words) | 2 | | Wrapper premium percentage | 20 | 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | Gas price _ (Coordinator overhead gas + Callback gas limit + Wrapper gas overhead + (Coordinator overhead gas per word _ Number of words)) | | | 50 gwei x (112000 + 100000 + 13400 + (435 \* 2)) | 11313500 gwei (0.0113135 ETH) | 2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.004 ETH per 1 LINK. | ETH to LINK cost conversion | Total gas cost (LINK) | | ------------------------------ | --------------------- | | 0.0113135 ETH / 0.004 ETH/LINK | 2.828375 LINK | 3. Apply the premium percentage to get the total cost of a request: | Applying premium percentage | Request cost (LINK) | | --------------------------------------------------------- | ------------------- | | Total gas cost (LINK) \* ((100 + premium percentage)/100) | | | (2.828375 LINK \* (100 + 20))/100) | 3.39405 LINK | This example request would cost 3.39405 LINK. ### Paying in ETH | Parameter | Value | | --------------------------------- | ------- | | Gas price | 50 gwei | | Callback gas limit | 100000 | | Coordinator gas overhead (Native) | 90000 | | Wrapper gas overhead | 13400 | | Coordinator gas overhead per word | 435 | | Number of random values (words) | 2 | | Wrapper premium percentage | 24 | 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | Gas price _ (Coordinator overhead gas + Callback gas limit + Wrapper gas overhead + (Coordinator overhead gas per word _ Number of words)) | | | 50 gwei x (90000 + 100000 + 13400 + (435 \* 2)) | 10213500 gwei (0.0102135 ETH) | 2. Apply the premium percentage to get the total cost of a request: | Applying premium percentage | Request cost (ETH) | | -------------------------------------------------------- | ------------------ | | Total gas cost (ETH) \* ((100 + premium percentage)/100) | | | (0.0102135 ETH \* (100 + 24))/100) | 0.01266474 ETH | This example request would cost 0.01266474 ETH. --- # Subscription Method Source: https://docs.chain.link/vrf/v2-5/overview/subscription This section explains how to generate random numbers using the subscription method. > **NOTE: Migrate to V2.5** > > Follow the [migration guide](/vrf/v2-5/migration-from-v2) to learn how VRF has changed in V2.5 and to get example > code. ## Subscriptions VRF v2.5 requests receive funding from subscription accounts. Creating a VRF subscription lets you create an account and pre-pay for VRF v2.5, so you don't provide funding each time your application requests randomness. This reduces the total gas cost to use VRF v2.5. It also provides a simple way to fund your use of Chainlink products from a single location, so you don't have to manage multiple wallets across several different systems and applications. Subscriptions have the following core concepts: - **Subscription id:** 256-bit unsigned integer representing the unique identifier of the subscription. - **Subscription accounts:** An account that holds LINK and native tokens and makes them available to fund requests to Chainlink VRF v2.5 coordinators. - **Subscription owner:** The wallet address that creates and manages a subscription account. Any account can add LINK or native tokens to the subscription balance, but only the owner can add approved consuming contracts or withdraw funds. - **Consumers:** Consuming contracts that are approved to use funding from your subscription account. - **Subscription balance:** The amount of funds in LINK or native tokens maintained on your subscription account. Your subscription can maintain balances for both LINK and native tokens. Requests from consuming contracts will continue to be funded until the balance runs out, so be sure to maintain sufficient funds in your subscription balance to pay for the requests and keep your applications running. For Chainlink VRF v2.5 to fulfill your requests, you must maintain a sufficient amount of LINK or native tokens in your subscription balance. Gas cost calculation includes the following variables: - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. - **Verification gas:** The amount of gas used to verify randomness onchain. The gas price depends on current network conditions. The callback gas depends on your callback function, and the number of random values in your request. The cost of each request is final only after the transaction is complete, but you define the limits you are willing to spend for the request with the following variables: - **Gas lane:** The maximum gas price you are willing to pay for a request in wei. Define this limit by specifying the appropriate `keyHash` in your request. The limits of each gas lane are important for handling gas price spikes when Chainlink VRF bumps the gas price to fulfill your request quickly. - **Callback gas limit:** Specifies the maximum amount of gas you are willing to spend on the callback request. Define this limit by specifying the `callbackGasLimit` value in your request. ## Request and receive data Requests to Chainlink VRF v2.5 follow the request and receive data cycle similarly to VRF V2. This end-to-end diagram shows each step in the lifecycle of a VRF subscription request, and registering a smart contract with a VRF subscription account: ![Image](/images/vrf/v2-5/subscription-architecture-diagram.png) VRF v2.5 uses both offchain and onchain components: - [VRF v2.5 Coordinator (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol): A contract designed to interact with the VRF service. It emits an event when a request for randomness is made, and then verifies the random number and proof of how it was generated by the VRF service. - VRF service (offchain component): Listens for requests by subscribing to the VRF Coordinator event logs and calculates a random number based on the block hash and nonce. The VRF service then sends a transaction to the `VRFCoordinator` including the random number and a proof of how it was generated. ### Account types used in VRF Two types of accounts exist in the Ethereum ecosystem, and both are used in VRF: - Externally Owned Account (EOA): An externally owned account that has a private key and can control a smart contract. Transactions can only be initiated by EOAs. - Smart contract: A contract that does not have a private key and executes what it has been designed for as a decentralized application. While only EOAs can initiate transactions, do **not** attempt to use EOAs to send VRF requests directly. Instead, your EOA should interact with your consuming contract: the smart contract that is consuming the random values you request from VRF. Your EOA initiates the transaction, and then your consuming contract sends the VRF request. ### Set up your contract and request Set up your consuming contract: 1. Your contract must inherit [VRFConsumerBaseV2Plus](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol). 2. Your contract must implement the `fulfillRandomWords` function, which is the *callback VRF function*. Here, you add logic to handle the random values after they are returned to your contract. 3. Submit your VRF request by calling `requestRandomWords` of the [VRF Coordinator](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol). Include the following parameters in your request: - `keyHash`: Identifier that maps to a job and a private key on the VRF service and that represents a specified gas lane. If your request is urgent, specify a gas lane with a higher gas price limit. The configuration for your network can be found [here](/vrf/v2-5/supported-networks). - `s_subscriptionId`: The subscription ID that the consuming contract is registered to. LINK funds are deducted from this subscription. - `requestConfirmations`: The number of block confirmations the VRF service will wait to respond. The minimum and maximum confirmations for your network can be found [here](/vrf/v2-5/supported-networks). - `callbackGasLimit`: The maximum amount of gas a user is willing to pay for completing the callback VRF function. Note that you cannot put a value larger than `maxGasLimit` of the VRF Coordinator contract (read [coordinator contract limits](#limits) for more details). - `numWords`: The number of random numbers to request. The maximum random values that can be requested for your network can be found [here](/vrf/v2-5/supported-networks). In VRF 2.5, the request format has changed: ```solidity uint256 requestID = s_vrfCoordinator.requestRandomWords(VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: subId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) // new parameter }) ); ``` 1. Add the `setCoordinator` method to your contract. This makes it easier to update your contract for future VRF releases by setting the new coordinator. ### How VRF processes your request After you submit your request, it is processed using the [Request & Receive Data](#request-and-receive-data) cycle. The VRF coordinator processes the request and determines the final charge to your subscription using the following steps: 1. The VRF coordinator emits an event. 2. The VRF service picks up the event and waits for the specified number of block confirmations to respond back to the VRF coordinator with the random values and a proof (`requestConfirmations`). 3. The VRF coordinator verifies the proof onchain, then it calls back the consuming contract `fulfillRandomWords` function. ## Limits Chainlink VRF v2.5 has [subscription limits](#subscription-limits) and [coordinator contract limits](#coordinator-contract-limits). ### Subscription limits Subscriptions are required to maintain a minimum balance, and they can support a limited number of consuming contracts. #### Minimum subscription balance Each subscription must maintain a minimum balance to fund requests from consuming contracts. This minimum balance requirement serves as a buffer against gas volatility by ensuring that all your requests have more than enough funding to go through. If your balance is below the minimum, your requests remain pending for up to 24 hours before they expire. After you add sufficient LINK or native tokens to a subscription, pending requests automatically process as long as they have not expired. In the Subscription Manager, the minimum subscription balance is displayed as the **Max Cost**, and it indicates the amount of LINK or native tokens you need to add for a pending request to process. After the request is processed, only the amount actually consumed by the request is deducted from your balance. For example, if you are paying for your VRF requests in LINK and your minimum balance is 10 LINK, but your subscription balance is 5 LINK, you need to add at least 5 more LINK for your request to process. This does not mean that your request will ultimately cost 10 LINK. If the request ultimately costs 3 LINK after it has processed, then 3 LINK is deducted from your subscription balance. The same concept applies if you are paying in native tokens. The minimum subscription balance must be sufficient for each new consuming contract that you add to a subscription. For example, the minimum balance for a subscription that supports 20 consuming contracts needs to cover all the requests for all 20 contracts, while a subscription with one consuming contract only needs to cover that one contract. For one request, the required size of the minimum balance depends on the gas lane and the size of the request. For example, a consuming contract that requests one random value will require a smaller minimum balance than a consuming contract that requests 50 random values. In general, you can estimate the required minimum balance using the following formula where max verification gas is always 200,000 gwei. The following formulas show how the minimum subscription balance is calculated for LINK and native tokens in general. [Specific examples of each](/vrf/v2-5/billing#estimate-minimum-subscription-balance) are available on the Billing page, where you can compare the higher minimum subscription balance with the lower amount for an actual request. ### LINK ``` (((Gas lane maximum * (Max verification gas + Callback gas limit)) * (100 + premium %)/100) / (1,000,000,000 Gwei/ETH)) / (ETH/LINK price) = Minimum LINK ``` Here is the same formula, broken out into steps: ``` Gas lane maximum * (Max verification gas + Callback gas limit) = Total estimated gas (Gwei) Total estimated gas (Gwei) * ((100 + premium %)/100) = Total estimated gas with premium (Gwei) Total estimated gas with premium (Gwei) / 1,000,000,000 Gwei/ETH = Total estimated gas with premium (ETH) Total estimated gas with premium (ETH) / (ETH/LINK price) = Total estimated gas with premium (LINK) ``` ### Native tokens ``` (((Gas lane maximum * (Max verification gas + Callback gas limit)) * (100 + premium %)/100) / (1,000,000,000 Gwei/ETH)) / (ETH/[Native token] price) = Minimum [Native token] ``` Here is the same formula, broken out into steps: ``` Gas lane maximum * (Max verification gas + Callback gas limit) = Total estimated gas (Gwei) Total estimated gas (Gwei) * ((100 + premium %)/100) = Total estimated gas with premium (Gwei) Total estimated gas with premium (Gwei) / 1,000,000,000 Gwei/ETH = Total estimated gas with premium (ETH) Total estimated gas with premium (ETH) / (ETH/[Native token] price) = Total estimated gas with premium (Native token) ``` #### Maximum consuming contracts Each subscription supports up to 100 consuming contracts. If you need more than 100 consuming contracts, create multiple subscriptions. ### Coordinator contract limits You can see the configuration for each network on the [Supported networks](/vrf/v2-5/supported-networks) page. You can also view the full configuration for each coordinator contract directly in the block explorer for that network, for example, Etherscan or Polygonscan. - Each coordinator has a `MAX_NUM_WORDS` parameter that limits the maximum number of random values you can receive in each request. - Each coordinator has a `maxGasLimit` parameter, which is the maximum allowed `callbackGasLimit` value for your requests. You must specify a sufficient `callbackGasLimit` to fund the callback request to your consuming contract. This depends on the number of random values you request and how you process them in your `fulfillRandomWords()` function. If your `callbackGasLimit` is not sufficient, the callback fails but your subscription is still charged for the work done to generate your requested random values. --- # Direct Funding Method Source: https://docs.chain.link/vrf/v2-5/overview/direct-funding This guide explains how to generate random numbers using the *direct funding* method. This method doesn't require a subscription and is optimal for one-off requests for randomness. This method also works best for applications where your end-users must pay the fees for VRF because the cost of the request is determined at request time. > **NOTE: Migrate to V2.5** > > Follow the [migration guide](/vrf/v2-5/migration-from-v2) to learn how VRF has changed in V2.5 and to get example > code. Unlike the [subscription method](/vrf/v2-5/overview/subscription), the direct funding method does not require you to create subscriptions and pre-fund them. Instead, you must directly fund consuming contracts with native tokens or LINK before they request randomness. Because the consuming contract directly pays for the request, the cost is calculated during the request and not during the callback when the randomness is fulfilled. Learn [how to estimate costs](/vrf/v2-5/billing). ## Request and receive data Requests to Chainlink VRF v2.5 follow the request and receive data cycle similarly to VRF V2. This end-to-end diagram shows each step in the lifecycle of a VRF direct funding request: ![Image](/images/vrf/v2-5/direct-funding-architecture-diagram.png) The Chainlink VRF v2.5 solution uses both offchain and onchain components: - [VRF v2.5 Wrapper (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol): A wrapper for the VRF Coordinator that provides an interface for consuming contracts. - [VRF v2.5 Coordinator (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol): A contract designed to interact with the VRF service. It emits an event when a request for randomness is made, and then verifies the random number and proof of how it was generated by the VRF service. - VRF service (offchain component): Listens for requests by subscribing to the VRF Coordinator event logs and calculates a random number based on the block hash and nonce. The VRF service then sends a transaction to the `VRFCoordinator` including the random number and a proof of how it was generated. ### Account types used in VRF Two types of accounts exist in the Ethereum ecosystem, and both are used in VRF: - EOA (Externally Owned Account): An externally owned account that has a private key and can control a smart contract. Transactions can be initiated only by EOAs. - Smart contract: A smart contract that does not have a private key and executes what it has been designed for as a decentralized application. While only EOAs can initiate transactions, do not attempt to use EOAs to send VRF requests directly. Instead, your EOA should interact with your consuming contract: the smart contract that is consuming the random values you request from VRF. Your EOA initiates the transaction, and then your consuming contract interacts with the VRF Wrapper contract, which sends the VRF request. ### Set up your contract and request Set up your consuming contract: 1. Your contract must inherit [VRFV2PlusWrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol). 2. Your contract must implement the `fulfillRandomWords` function, which is the *callback VRF function*. Here, you add logic to handle the random values after they are returned to your contract. 3. Submit your VRF request by calling the `requestRandomness` function in the [VRFV2PlusWrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) contract. Include the following parameters in your request: - `requestConfirmations`: The number of block confirmations the VRF service will wait to respond. The minimum and maximum confirmations for your network can be found [here](/vrf/v2-5/supported-networks). - `callbackGasLimit`: The maximum amount of gas to pay for completing the callback VRF function. - `numWords`: The number of random numbers to request. You can find the maximum number of random values per request for your network in the [Supported networks](/vrf/v2-5/supported-networks) page. - `extraArgs`: A parameter for additional arguments related to new VRF features, such as enabling payment in native tokens. ### How VRF processes your request After you submit your request, it is processed using the [Request & Receive Data](#request-and-receive-data) cycle: 1. The consuming contract calls the [VRFV2PlusWrapper](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol) `calculateRequestPrice` function to estimate the total transaction cost to fulfill randomness. Learn [how to estimate transaction costs](/vrf/v2-5/billing). 2. The consuming contract calls the [LinkToken](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol) `transferAndCall` function to pay the wrapper with the calculated request price. This method sends LINK tokens and executes the [VRFV2PlusWrapper](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol) `onTokenTransfer` logic. 3. The VRFV2PlusWrapper's `onTokenTransfer` logic triggers the [VRF 2.5 Coordinator](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol) `requestRandomWords` function to request randomness. 4. The VRF coordinator emits an event. 5. The VRF service picks up the event and waits for the specified number of block confirmations to respond back to the VRF coordinator with the random values and a proof (`requestConfirmations`). 6. The VRF coordinator verifies the proof onchain, then it calls back the wrapper contract's `fulfillRandomWords` function. 7. Finally, the VRF Wrapper calls back your consuming contract. ## Limits You can see the configuration for each network on the [Supported networks](/vrf/v2-5/supported-networks) page. You can also view the full configuration for each VRF v2.5 Wrapper contract directly in Etherscan. As an example, view the [Ethereum Mainnet VRF v2.5 Wrapper contract](https://etherscan.io/address/0x02aae1A04f9828517b3007f83f6181900CaD910c#readContract) configuration by calling `getConfig` function. - Each wrapper has a `maxNumWords` parameter that limits the maximum number of random values you can receive in each request. - The maximum allowed `callbackGasLimit` value for your requests is defined in the [Coordinator contract supported networks](/vrf/v2-5/supported-networks) page. Because the VRF v2.5 Wrapper adds an overhead, your `callbackGasLimit` must not exceed `maxGasLimit - wrapperGasOverhead`. Learn more about [estimating costs](/vrf/v2-5/billing). --- # VRF Cost Estimation on Arbitrum Source: https://docs.chain.link/vrf/v2-5/arbitrum-cost-estimation The total transaction costs for using Arbitrum involve both L2 gas costs and L1 costs. Arbitrum transactions are [posted in batches to L1 Ethereum](https://developer.arbitrum.io/inside-arbitrum-nitro/#how-the-sequencer-publishes-the-sequence), which incurs an L1 cost. For an individual transaction, the total cost includes part of the L1 cost incurred to post the batch that included the transaction. To learn how to estimate gas costs for Arbitrum, refer to the [Arbitrum gas estimation tutorial](https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas) and the full [Arbitrum gas estimation script](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/gas-estimation) using their SDK. There is also a [**version of Arbitrum's gas estimation script extended to include VRF calculations**](#arbitrum-and-vrf-gas-estimation-code). #### Estimating Arbitrum gas costs with VRF ### Subscription VRF gas costs on L1 networks are calculated based on the amount of verification gas and callback gas used, multiplied by the gas price: ``` (Gas price * (Verification gas + Callback gas)) = total gas cost ``` For VRF Arbitrum transactions, add a buffer to estimate the additional L1 cost: ``` (L2GasPrice * (Verification gas + Callback gas + L1 calldata gas buffer))) = total estimated gas cost ``` To calculate the L1 callback gas buffer: - `calldataSizeBytes`: A static size for the transaction's calldata in bytes. Total: 720 bytes. - The amount Arbitrum adds to account for the static part of the transaction, fixed at 140 bytes. - The size of an ABI-encoded VRF V2.5 fulfillment, fixed at 580 bytes (`fulfillmentTxSizeBytes`). - `L1PricePerByte`: The estimated cost of posting 1 byte of data on L1, which varies with L1 network gas prices. - `L2GasPrice`: The L2 gas price, which varies with L2 network gas prices. ``` L1 calldata gas buffer = (calldataSizeBytes * L1PricePerByte) / L2GasPrice = (720 * L1PricePerByte) / L2GasPrice ``` This conversion allows us to estimate the L1 callback gas cost and incorporate it into the overall L2 gas estimate. You can add this estimated L1 callback gas buffer directly to the verification and callback gas: ``` (L2GasPrice * (Verification gas + Callback gas + ((calldataSizeBytes * L1PricePerByte) / L2GasPrice)))) = total estimated gas cost ``` ### Direct funding VRF gas costs on L1 networks are calculated based on the amount of coordinator overhead gas, wrapper overhead gas, and callback gas, multiplied by the gas price: ``` (Gas price * (Coordinator overhead gas + Callback gas + Wrapper overhead gas)) = total gas cost ``` For VRF Arbitrum transactions, add a buffer to estimate the additional L1 cost: ``` (L2GasPrice * (Coordinator overhead gas + Callback gas + Wrapper overhead gas + L1 calldata gas buffer))) = total estimated gas cost ``` To calculate the L1 callback gas buffer: - `calldataSizeBytes`: A static size for the transaction's calldata in bytes. Total: 720 bytes. - The amount Arbitrum adds to account for the static part of the transaction, fixed at 140 bytes. - The size of an ABI-encoded VRF V2.5 fulfillment, fixed at 580 bytes (`fulfillmentTxSizeBytes`). - `L1PricePerByte`: The estimated cost of posting 1 byte of data on L1, which varies with L1 network gas prices. - `L2GasPrice`: The L2 gas price, which varies with L2 network gas prices. ``` L1 calldata gas buffer = (calldataSizeBytes * L1PricePerByte) / L2GasPrice = (720 * L1PricePerByte) / L2GasPrice ``` This conversion allows us to estimate the L1 callback gas cost and incorporate it into the overall L2 gas estimate. You can add this estimated L1 callback gas buffer directly to the other gas figures: ``` (L2GasPrice * (Coordinator overhead gas + Callback gas + Wrapper overhead gas + ((calldataSizeBytes * L1PricePerByte) / L2GasPrice)))) = total estimated gas cost ``` #### Arbitrum and VRF gas estimation code This sample extends the [original Arbitrum gas estimation script](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/gas-estimation) to estimate gas costs for VRF subscription and direct funding requests on Arbitrum. The following snippet shows only the VRF variables and calculations that were added to the Arbitrum gas estimation script. To learn more about how Arbitrum gas is calculated, refer to the [Arbitrum gas estimation tutorial](https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas). To run this code, use the [**full Arbitrum gas estimation script that includes VRF calculations**](https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf-arbitrum-gas-estimation). ```typescript // VRF variables and calculations // --------------------------------- // Full script: https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf-arbitrum-gas-estimation // --------------------------------- // Estimated upper bound of verification gas for VRF subscription. // To see an estimate with an average amount of verification gas, // adjust this to 115000. const maxVerificationGas = 200000 // The L1 Calldata size includes: // Arbitrum's static 140 bytes for transaction metadata // VRF V2's static 580 bytes, the size of a fulfillment's calldata abi-encoded in bytes // (from s_fulfillmentTxSizeBytes in VRFV2Wrapper.sol) const VRFCallDataSizeBytes = 140 + 580 // For direct funding only // Coordinator gas is verification gas. // Some overhead gas values vary by network. These are hardcoded for Sepolia. // Refer to https://docs.chain.link/vrf/v2-5/supported-networks to find values for other networks. const wrapperGasOverhead = 13400 const coordinatorGasOverheadNative = 90000 const coordinatorGasOverheadLink = 112000 const coordinatorGasOverheadPerWord = 435 // VRF user settings const callbackGasLimit = 175000 const numWords = 2 // Max 10 per request // Estimate VRF L1 buffer const VRFL1CostEstimate = L1P.mul(VRFCallDataSizeBytes) const VRFL1Buffer = VRFL1CostEstimate.div(P) // VRF Subscription gas estimate // L2 gas price (P) * (maxVerificationGas + callbackGasLimit + VRFL1Buffer) const VRFL2SubscriptionGasSubtotal = BigNumber.from(maxVerificationGas + callbackGasLimit) const VRFSubscriptionGasTotal = VRFL2SubscriptionGasSubtotal.add(VRFL1Buffer) const VRFSubscriptionGasEstimate = P.mul(VRFSubscriptionGasTotal) // VRF Direct funding gas estimate // L2 gas price (P) * (coordinatorGasOverheadLink + callbackGasLimit + wrapperGasOverhead + VRFL1Buffer) // If using native tokens, change coordinatorGasOverheadLink to coordinatorGasOverheadNative below const directFundingGasOverheadPerWord = coordinatorGasOverheadPerWord.mul(numWords) const VRFL2DirectFundingGasSubtotal = BigNumber.from( coordinatorGasOverheadLink + wrapperGasOverhead + callbackGasLimit + directFundingGasOverheadPerWord ) const VRFDirectFundingGasTotal = VRFL2DirectFundingGasSubtotal.add(VRFL1Buffer) const VRFDirectFundingGasEstimate = P.mul(VRFDirectFundingGasTotal) ``` --- # Create and manage VRF V2.5 subscriptions Source: https://docs.chain.link/vrf/v2-5/subscription/create-manage ## Using the VRF Subscription Manager The [VRF Subscription Manager](https://vrf.chain.link/) is available to help you create and manage VRF V2.5 subscriptions. You can create and manage new V2.5 subscriptions, and manage existing V2 subscriptions, but you can no longer create new V2 subscriptions in the VRF Subscription Manager. Alternatively, you can [create and manage subscriptions programmatically](#create-a-subscription-programmatically). ### Create a subscription To create a VRF 2.5 subscription: 1. Use the VRF Subscription Manager at [vrf.chain.link](https://vrf.chain.link/). Connect your wallet in the upper right corner and then click **Create subscription**. The address of your connected wallet is automatically filled in the **Admin** address field. 2. When the subscription is successfully created, there will be an alert in the upper right corner telling you that the subscription was successfully created. Click **Home** to navigate back to your main dashboard. 3. Your new subscription shows in the **My Subscriptions** list, along with any previous V2 subscriptions you might have. Click the Subscription ID for your new subscription in the list. ### Add a consumer To add a consuming contract: 1. On the details page for your subscription, select **Add Consumer**. 2. Provide the address of your consuming contract, and then select **Add Consumer** again. Confirm the resulting prompts in MetaMask or other wallet browser extension. ### Fund your subscription To fund your subscription: 1. On the page for your subscription, select the **Actions** menu and then select **Fund subscription**. 2. Your subscription has two balances: one for LINK, and one for the native token. Expand the **Asset** menu to select either LINK or the native token. 3. In **Amount to fund**, enter the amount you want to fund your subscription. Your wallet balance is displayed below the **Asset** field for easier reference. Select **Confirm** to fund your wallet, and then confirm the resulting prompts in MetaMask or other wallet browser extension. ### Cancel your subscription and withdraw funds To withdraw your funds from a subscription, you must cancel the subscription. 1. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link/) and click the ID of your new subscription under the **My Subscriptions** list. The subscription details page opens. 2. On your subscription details page, expand the **Actions** menu and select **Cancel subscription**. A field displays, prompting you to add the wallet address you want to send the remaining funds to. 3. Enter your wallet address and click **Cancel subscription**. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF closes your subscription account and sends the remaining LINK to your wallet. If your subscription's admin address is a contract instead of an EOA, you may not be able to cancel the subscription directly. In this case, you must transfer ownership of your subscription to an EOA so that you can cancel the subscription and withdraw your funds. ## Create a subscription programmatically If you prefer to create, fund and manage your subscriptions programmatically, you can either deploy a subscription manager contract or use your network's block explorer: 1. Create a new subscription for VRF v2.5: ### Subscription contract Deploy the [`SubscriptionManager` contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionManager.sol). On deployment, the contract creates a new subscription and adds itself as a consumer to the new subscription. ### Using a block explorer 1. Navigate to the VRF coordinator contract on the block explorer for the network you want to use (for example, Etherscan or Polygonscan). You can find the coordinator addresses with links to the block explorers on the [Supported Networks](/vrf/v2-5/supported-networks) page. 2. In the **Contract** tab, select the **Write contract** tab. Connect your wallet to the block explorer. 3. Expand the `createSubscription` function and select the **Write** button. Follow the prompts in MetaMask to confirm the transaction. 4. Get your subscription ID for the next step, funding your subscription. 2. Fund your new VRF v2.5 subscription: ### Subscription contract 1. [Fund your new `VRFv2PlusSubscriptionManager` contract](/resources/fund-your-contract). 2. Call `topUpSubscription` from the `VRFv2PlusSubscriptionManager` contract. This function uses the LINK token contract's `transferAndCall` function to fund your new subscription. ### Using a block explorer 1. [Fund your new `VRFv2PlusSubscriptionManager` contract](/resources/fund-your-contract). 2. Navigate to the LINK token contract on the block explorer for the network you want to use (for example, Etherscan or Polygonscan). You can find the LINK token contract addresses with links to the block explorers on the [Supported Networks](/vrf/v2-5/supported-networks) page. 3. In the **Contract** tab, select the **Write contract** tab. Connect your wallet to the block explorer. 4. Expand the `transferAndCall` function and fill in the following parameters: - **to(address)**: The address of the VRF coordinator. - **value(uint256)**: The amount you want to fund your subscription with. - **data(bytes)**: The ABI-encoded subscription ID. 5. Select the **Write** button and follow the prompts in MetaMask to confirm the transaction. --- # Get a Random Number Source: https://docs.chain.link/vrf/v2-5/subscription/get-a-random-number This guide explains how to get random values using a simple contract to request and receive random values from Chainlink VRF v2.5. The guide uses the Subscription Manager to create and manage your subscription. Alternatively, you can also [create and manage subscriptions programmatically](/vrf/v2-5/subscription/create-manage#create-a-subscription-programmatically). To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Requirements This guide assumes that you know how to create and deploy smart contracts on Ethereum testnets using the following tools: - [The Remix IDE](https://remix.ethereum.org/) - [MetaMask](https://metamask.io/) - [Sepolia testnet ETH](/resources/link-token-contracts/#sepolia-testnet) If you are new to developing smart contracts on Ethereum, see the [Getting Started](/getting-started/conceptual-overview) guide to learn the basics. ## Create and fund a subscription For this example, create a new subscription on the Sepolia testnet. 1. Open MetaMask and set it to use the Sepolia testnet. The [Subscription Manager](https://vrf.chain.link) detects your network based on the active network in MetaMask. 2. Check MetaMask to make sure you have testnet ETH and LINK on Sepolia. You can get testnet ETH and LINK at [faucets.chain.link/sepolia](https://faucets.chain.link/sepolia/). 3. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link). [Open the Subscription Manager](https://vrf.chain.link) 4. Click **Create Subscription** and follow the instructions to create a new subscription account. If you connect your wallet to the Subscription Manager, the **Admin address** for your subscription is prefilled and not editable. Optionally, you can enter an email address and a project name for your subscription, and both of these are private. MetaMask opens and asks you to confirm payment to create the account onchain. After you approve the transaction, the network confirms the creation of your subscription account onchain. 5. After the subscription is created, click **Add funds** and follow the instructions to fund your subscription. For your request to go through, you need to fund your subscription with enough testnet funds to meet your [minimum subscription balance](/vrf/v2-5/overview/subscription#minimum-subscription-balance) to serve as a buffer against gas volatility. - If you're paying with testnet LINK, fund your contract with 7 LINK. (After your request is processed, the actual cost will be around 0.06 LINK, and that amount will be deducted from your subscription balance.) - If you're paying with testnet ETH, fund your contract with 0.03 ETH. (After your request is processed, the actual cost will be around 0.000247 ETH, and that amount will be deducted from your subscription balance.) MetaMask opens to confirm the token transfer to your subscription. After you approve the transaction, the network confirms the transfer of your testnet funds to your subscription account. 6. After you add funds, click **Add consumer**. A page opens with your account details and subscription ID. 7. Record your subscription ID, which you need for your consuming contract. You will add the consuming contract to your subscription later. You can always find your subscription IDs, balances, and consumers at [vrf.chain.link](https://vrf.chain.link/). Now that you have a funded subscription account and your subscription ID, [create and deploy a VRF compatible contract](#create-and-deploy-a-vrf-compatible-contract). ## Create and deploy a VRF compatible contract For this example, use the [SubscriptionConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionConsumer.sol) sample contract. This contract imports the following dependencies: - `VRFConsumerBaseV2Plus.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) - `VRFV2PlusClient.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol) The contract also includes pre-configured values for the necessary request parameters such as `vrfCoordinator` address, gas lane `keyHash`, `callbackGasLimit`, `requestConfirmations` and number of random words `numWords`. You can change these parameters if you want to experiment on different testnets, but for this example you only need to specify `subscriptionId` when you deploy the contract. Build and deploy the contract on Sepolia. 1. Open the [SubscriptionConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionConsumer.sol) in Remix. [Open SubscriptionConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/SubscriptionConsumer.sol) 2. On the **Compile** tab in Remix, compile the `SubscriptionConsumer.sol` contract. 3. Configure your deployment. On the **Deploy** tab in Remix, select the **Injected Provider** environment, select the `SubscriptionConsumer` contract from the contract list, and specify your `subscriptionId` so the constructor can set it. ![Example showing the deploy button with the subscriptionID field filled in Remix](/images/vrf/v2-5/deploy-with-sub-id-filled.png) 4. Click the **Deploy** button to deploy your contract onchain. MetaMask opens and asks you to confirm the transaction. 5. After you deploy your contract, copy the address from the **Deployed Contracts** list in Remix. Before you can request randomness from VRF v2.5, you must add this address as an approved consuming contract on your subscription account. ![Example showing the contract address listed under the Contracts list in Remix](/images/vrf/v2-5/contract-address-copy-button.png) 6. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link/) and click the ID of your new subscription under the **My Subscriptions** list. The subscription details page opens. 7. Under the **Consumers** section, click **Add consumer**. 8. Enter the address of your consuming contract that you just deployed and click **Add consumer**. MetaMask opens and asks you to confirm the transaction. Your example contract is deployed and approved to use your subscription balance to pay for VRF v2.5 requests. Next, [request random values](#request-random-values) from Chainlink VRF. ## Request random values The deployed contract requests random values from Chainlink VRF, receives those values, builds a struct `RequestStatus` containing them and stores the struct in a mapping `s_requests`. Run the `requestRandomWords()` function on your contract to start the request. 1. Return to Remix and view your deployed contract functions in the **Deployed Contracts** list. 2. Expand the `requestRandomWords()` function to send the request for random values to Chainlink VRF. Use `enableNativePayment` to specify whether you want to pay in native tokens or LINK: - To use native tokens, set `enableNativePayment` to `true`. - To use LINK, set `enableNativePayment` to `false`. When you click **transact**, MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF processes your request. Chainlink VRF fulfills the request and returns the random values to your contract in a callback to the `fulfillRandomWords()` function. At this point, a new key `requestId` is added to the mapping `s_requests`. Depending on current testnet conditions, it might take a few minutes for the callback to return the requested random values to your contract. You can see a list of pending requests for your subscription ID at [vrf.chain.link](https://vrf.chain.link/). 3. To fetch the request ID of your request, call `lastRequestId()`. 4. After the oracle returns the random values to your contract, the mapping `s_requests` is updated: The received random values are stored in `s_requests[_requestId].randomWords`. 5. Call `getRequestStatus()` specifying the `requestId` to display the random words. You deployed a simple contract that can request and receive random values from Chainlink VRF. Next, learn how to [create and manage subscriptions programmatically](/vrf/v2-5/subscription/create-manage#create-a-subscription-programmatically) by using a smart contract instead of the Subscription Manager. > **NOTE: Note on Requesting Randomness** > > Do not allow re-requesting or cancellation of randomness. For more information, see the [VRF Security > Considerations](/vrf/v2-5/security#do-not-allow-re-requesting-or-cancellation-of-randomness) page. ## Analyzing the contract In this example, your MetaMask wallet is the subscription owner and you created a consuming contract to use that subscription. The consuming contract uses static configuration parameters. ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.20; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract SubscriptionConsumer is VRFConsumerBaseV2Plus { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords); struct RequestStatus { bool fulfilled; // whether the request has been successfully fulfilled bool exists; // whether a requestId exists uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ // Your subscription ID. uint256 public s_subscriptionId; // Past request IDs. uint256[] public requestIds; uint256 public lastRequestId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/vrf/v2-5/supported-networks bytes32 public keyHash = 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 public callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 public requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2_5.MAX_NUM_WORDS. uint32 public numWords = 2; /** * HARDCODED FOR SEPOLIA * COORDINATOR: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B */ constructor( uint256 subscriptionId ) VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) { s_subscriptionId = subscriptionId; } // Assumes the subscription is funded sufficiently. // @param enableNativePayment: Set to `true` to enable payment in native tokens, or // `false` to pay in LINK function requestRandomWords( bool enableNativePayment ) external onlyOwner returns (uint256 requestId) { // Will revert if subscription is not set and funded. requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: keyHash, subId: s_subscriptionId, requestConfirmations: requestConfirmations, callbackGasLimit: callbackGasLimit, numWords: numWords, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment})) }) ); s_requests[requestId] = RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false}); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] calldata _randomWords ) internal override { require(s_requests[_requestId].exists, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords); } function getRequestStatus( uint256 _requestId ) external view returns (bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].exists, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.fulfilled, request.randomWords); } } ``` The parameters define how your requests will be processed. You can find the values for your network in the [Configuration](/vrf/v2-5/supported-networks) page. - `uint256 s_subscriptionId`: The subscription ID that this contract uses for funding requests. - `bytes32 keyHash`: The gas lane key hash value, which is the maximum gas price you are willing to pay for a request in wei. It functions as an ID of the offchain VRF job that runs in response to requests. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords()` function. It must be less than the `maxGasLimit` limit on the coordinator contract. Adjust this value for larger requests depending on how your `fulfillRandomWords()` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your subscription is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` limit on the coordinator contract. - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. The total cost of the callback request depends on how your `fulfillRandomWords()` function processes and stores the received random values, so adjust your `callbackGasLimit` accordingly. The contract includes the following functions: - `requestRandomWords(bool enableNativePayment)`: Takes your specified parameters and submits the request to the VRF coordinator contract. Use `enableNativePayment` to specify for each request whether you want to pay in native tokens or LINK: - To use native tokens, set `enableNativePayment` to `true`. - To use LINK, set `enableNativePayment` to `false`. - `fulfillRandomWords()`: Receives random values and stores them with your contract. - `getRequestStatus()`: Retrieve request details for a given `_requestId`. > **NOTE: Security Considerations** > > Be sure to review your contracts to make sure they follow the best practices on the [security > considerations](/vrf/v2-5/security) page. ## Clean up After you are done with this contract and the subscription, you can retrieve the remaining testnet tokens to use with other examples. 1. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link/) and click the ID of your new subscription under the **My Subscriptions** list. The subscription details page opens. 2. On your subscription details page, expand the **Actions** menu and select **Cancel subscription**. A field displays, prompting you to add the wallet address you want to send the remaining funds to. 3. Enter your wallet address and click **Cancel subscription**. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF closes your subscription account and sends the remaining LINK to your wallet. --- # Local testing using a mock subscription contract Source: https://docs.chain.link/vrf/v2-5/subscription/test-locally This guide explains how to test Chainlink VRF v2.5 on a [Remix IDE](https://remix-ide.readthedocs.io/en/latest/run.html#environment) sandbox blockchain environment. **Note**: You can reuse the same logic on another development environment, such as Hardhat or Foundry. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js). > **CAUTION: Test on public testnets thoroughly** > > Even though local testing has several benefits, testing with a VRF mock covers the bare minimum of use cases. Make > sure to test your consumer contract thoroughly on public testnets. ## Benefits of local testing ## Testing logic Complete the following tasks to test your VRF v2.5 consumer locally: 1. Deploy the [VRFCoordinatorV2_5Mock](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol). This contract is a mock of the [VRFCoordinatorV2_5](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol) contract. 2. Call the [createSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol#L56) (which `VRFCoordinatorV2_5Mock` inherits) to create a new subscription. 3. Call the VRFCoordinatorV2_5Mock [`fundSubscription` function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol#L174) to fund your newly created subscription. **Note**: You can fund with an arbitrary amount. 4. Deploy your VRF consumer contract. 5. Call the [addConsumer function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol#L12) (which `VRFCoordinatorV2_5Mock` inherits) to add your consumer contract to your subscription. 6. Request random words from your consumer contract. 7. Call the VRFCoordinatorV2_5Mock [fulfillRandomWords function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol#L101) to fulfill your consumer contract request. ## Testing ### Open the contracts on Remix IDE For local testing, use the default "Remix VM" environment. Open *VRFv2_5Consumer* and compile in Remix: ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.20; import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ /** * @title The RandomNumberConsumerV2_5 contract * @notice A contract that gets random values from Chainlink VRF V2_5 */ contract RandomNumberConsumerV2_5 is VRFConsumerBaseV2Plus { // Your subscription ID. uint256 immutable s_subscriptionId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf-contracts/#configurations bytes32 immutable s_keyHash; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 constant CALLBACK_GAS_LIMIT = 100_000; // The default is 3, but you can set this higher. uint16 constant REQUEST_CONFIRMATIONS = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2_5.MAX_NUM_WORDS. uint32 constant NUM_WORDS = 2; uint256[] public s_randomWords; uint256 public s_requestId; event ReturnedRandomness(uint256[] randomWords); /** * @notice Constructor inherits VRFConsumerBaseV2Plus * * @param subscriptionId - the subscription ID that this contract uses for funding requests * @param vrfCoordinator - coordinator, check https://docs.chain.link/vrf/v2-5/supported-networks * @param keyHash - the gas lane to use, which specifies the maximum gas price to bump to */ constructor( uint256 subscriptionId, address vrfCoordinator, bytes32 keyHash ) VRFConsumerBaseV2Plus(vrfCoordinator) { s_keyHash = keyHash; s_subscriptionId = subscriptionId; } /** * @notice Requests randomness * Assumes the subscription is funded sufficiently; "Words" refers to unit of data in Computer Science */ function requestRandomWords() external onlyOwner { // Will revert if subscription is not set and funded. s_requestId = s_vrfCoordinator.requestRandomWords( VRFV2PlusClient.RandomWordsRequest({ keyHash: s_keyHash, subId: s_subscriptionId, requestConfirmations: REQUEST_CONFIRMATIONS, callbackGasLimit: CALLBACK_GAS_LIMIT, numWords: NUM_WORDS, extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) }) ); } /** * @notice Callback function used by VRF Coordinator * * @param - id of the request * @param randomWords - array of random results from VRF Coordinator */ function fulfillRandomWords( uint256, /* requestId */ uint256[] calldata randomWords ) internal override { s_randomWords = randomWords; emit ReturnedRandomness(randomWords); } } ``` Open *VRFCoordinatorV2_5Mock* in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol"; ``` On the *Solidity Compiler* tab, expand the *Advanced Configurations* section and check the *Enable optimization* box before you compile the *VRFCoordinatorV2_5Mock* contract: ![Image](/images/vrf/v2-5/mock/enable-optimization.png) Your Remix IDE file explorer should display *VRFCoordinatorV2_5Mock.sol* and *VRFv2_5Consumer.sol*: ![Image](/images/vrf/v2-5/mock/file-explorer.png) ### Deploy VRFCoordinatorV2_5Mock 1. Open *VRFCoordinatorV2_5Mock.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *VRFCoordinatorV2_5Mock*. ![Image](/images/vrf/v2-5/mock/deployment-contracts-list.png) 3. Under *DEPLOY*, fill in the `_BASEFEE`, `_GASPRICELINK` and `_WEIPERUNITLINK`. These variables are used in the *VRFCoordinatorV2_5Mock* contract to represent the base fee, the gas price (in LINK tokens), and the current LINK/ETH price for the VRF requests. ![Image](/images/vrf/v2-5/mock/mock-deployment-parameters.png) You can set: - `_BASEFEE` to 100000000000000000 - `_GASPRICELINK` to 1000000000 - `_WEIPERUNITLINK` to the current LINK/ETH price. Click the "Latest Price" button to view it: 4. Click *transact* to deploy the *VRFCoordinatorV2_5Mock* contract. 5. Once deployed, you should see the *VRFCoordinatorV2_5Mock* contract under *Deployed Contracts*. ![Image](/images/vrf/v2-5/mock/deployed-mock.png) 6. Note the address of the deployed contract. ### Create and fund a subscription 1. Click `createSubscription` to create a new subscription. 2. In the Remix IDE console, read your transaction decoded output to find the subscription ID. Note the subscription ID, which is required for multiple steps in this tutorial. ![Image](/images/vrf/v2-5/mock/example-output-sub-id.png) 3. Click on `fundSubscription` to fund your subscription. Fill in your subscription ID for `_subid` and set the `_amount` to 100000000000000000000. This mocks funding your subscription with 100 LINK. ### Deploy the VRF consumer contract 1. In the file explorer, open *VRFv2_5Consumer.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *RandomNumberConsumerV2_5*. ![Image](/images/vrf/v2-5/mock/deploy-consumer.png) 3. Under *DEPLOY*, fill in the following parameters: - `SUBSCRIPTIONID` with your subscription ID - `VRFCOORDINATOR` with the deployed *VRFCoordinatorV2_5Mock* address - `_KEYHASH_` with an arbitrary `bytes32` (In this example, you can set the *KEYHASH* to 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae). 4. Click *transact* to deploy the *RandomNumberConsumerV2_5* contract. 5. After the consumer contract is deployed, you should see the *RandomNumberConsumerV2_5* contract under *Deployed Contracts*. Note the address of the deployed contract. ### Add the consumer contract to your subscription 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2_5Mock* contract. 2. Click *addConsumer* and fill in the `_subid` with your subscription ID and `_consumer` with your deployed consumer contract address. ![Image](/images/vrf/v2-5/mock/add-consumer.png) 3. Click *transact*. ### Request random words 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2_5* contract. 2. Click `requestRandomWords`. ![Image](/images/vrf/mock/v2-requestrandomwords.jpg) 3. Click `s_requestId` to display the last request ID. In this example, the output is *1*. ![Image](/images/vrf/v2-5/mock/show-last-request-id.png) 4. Note your request ID. ### Fulfill the VRF request Because you are testing on a local blockchain environment, you must fulfill the VRF request yourself. 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2_5Mock* contract. 2. Click `fulfillRandomWords` and fill in `_requestId` with your VRF request ID and `_consumer` with your consumer contract address. ![Image](/images/vrf/v2-5/mock/manual-fulfill-request.png) 3. Click `transact`. ### Check the results 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2_5* contract. 2. For each VRF request, your consumer contract requests two random words. After a request is fulfilled, the two random words are stored in the `s_randomWords` array. You can check the stored random words by reading the two first indexes of the `s_randomWords` array. To do so, click the *s_randomWords* function and: 1. Fill in the index with *0* then click *call* to read the first random word. ![Image](/images/vrf/v2-5/mock/show-random-word.png) 2. You can read the second random word in a similar way: fill in the index with *1* then click *call* to display the second random word. ## Next steps This guide demonstrated how to test a VRF v2.5 consumer contract on your local blockchain. The guide uses the Remix IDE for learning purposes, but you can reuse the same [testing logic](#testing-logic) in another development environment, such as Hardhat. For example, see the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js). --- # Get a Random Number Source: https://docs.chain.link/vrf/v2-5/direct-funding/get-a-random-number This guide explains how to get random values using a simple contract to request and receive random values from Chainlink VRF v2.5 without managing a subscription. To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Requirements This guide assumes that you know how to create and deploy smart contracts on Ethereum testnets using the following tools: - [The Remix IDE](https://remix.ethereum.org/) - [MetaMask](https://metamask.io/) - [Sepolia testnet ETH](/resources/link-token-contracts/#sepolia-testnet) If you are new to developing smart contracts on Ethereum, see the [Getting Started](/getting-started/conceptual-overview) guide to learn the basics. ## Create and deploy a VRF compatible contract For this example, use the [DirectFundingConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) sample contract. This contract imports the following dependencies: - `VRFV2PlusWrapperConsumerBase.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) - `VRFV2PlusClient.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol) The contract also includes pre-configured values for the necessary request parameters such as `callbackGasLimit`, `requestConfirmations`, the number of random words `numWords`, the VRF v2.5 Wrapper address `wrapperAddress`, and the LINK token address `linkAddress`. You can change these parameters if you want to experiment on different testnets. Build and deploy the contract on Sepolia. 1. Open the [`DirectFundingConsumer.sol` contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) in Remix. [Open DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/v2-5/DirectFundingConsumer.sol) 2. On the **Compile** tab in Remix, compile the `DirectFundingConsumer` contract. 3. Configure your deployment. On the **Deploy** tab in Remix, select the **Injected Web3 Environment** and select the `DirectFundingConsumer` contract from the contract list. 4. Click the **Deploy** button to deploy your contract onchain. MetaMask opens and asks you to confirm the transaction. 5. After you deploy your contract, copy the address from the **Deployed Contracts** list in Remix. Before you can request randomness from VRF v2.5, you must fund your consuming contract with enough tokens in order to request for randomness. Next, [fund your contract](#fund-your-contract). ## Fund your contract Requests for randomness will fail unless your consuming contract has enough tokens. VRF V2.5 allows you to use either native tokens or LINK to pay for your requests. 1. [Acquire testnet LINK and Sepolia ETH](https://faucets.chain.link/sepolia). 2. [Fund your contract](/resources/fund-your-contract) with either testnet LINK or Sepolia ETH, depending on how you want to pay for your VRF requests. For this example, fund your contract with 2 LINK or 0.01 Sepolia ETH. (The actual request cost is closer to 0.877 LINK or 0.001 ETH. You can [withdraw the excess funds](#clean-up) after you're done with this contract.) ## Request random values The deployed contract requests random values from Chainlink VRF, receives those values, builds a struct `RequestStatus` containing them, and stores the struct in a mapping `s_requests`. Run the `requestRandomWords()` function on your contract to start the request. 1. Return to Remix and view your deployed contract functions in the **Deployed Contracts** list. 2. Expand the `requestRandomWords()` function. For `enableNativePayment`, fill in `true` if you're paying for your request with Sepolia ETH, or `false` if you're paying with testnet LINK. Click **transact** to send the request for random values to Chainlink VRF. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF processes your request. Chainlink VRF fulfills the request and returns the random values to your contract in a callback to the `fulfillRandomWords()` function. At this point, a new key `requestId` is added to the mapping `s_requests`. Depending on current testnet conditions, it might take a few minutes for the callback to return the requested random values to your contract. 3. To fetch the request ID of your request, call `lastRequestId()`. 4. After the oracle returns the random values to your contract, the mapping `s_requests` is updated. The received random values are stored in `s_requests[_requestId].randomWords`. 5. Call `getRequestStatus()` and specify the `requestId` to display the random words. > **NOTE: Note on Requesting or Cancelling Randomness** > > Do not allow re-requesting or cancellation of randomness. For more information, see the [VRF Security > Considerations](/vrf/v2-5/security#do-not-allow-re-requesting-or-cancellation-of-randomness) page. ## Analyzing the contract In this example, the consuming contract uses static configuration parameters. ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity ^0.8.20; import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {VRFV2PlusWrapperConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol"; import {VRFV2PlusClient} from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract DirectFundingConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); struct RequestStatus { uint256 paid; // amount paid in link bool fulfilled; // whether the request has been successfully fulfilled uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 public callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 public requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFV2Wrapper.getConfig().maxNumWords. uint32 public numWords = 2; // Address LINK - hardcoded for Sepolia address public linkAddress = 0x779877A7B0D9E8603169DdbD7836e478b4624789; // address WRAPPER - hardcoded for Sepolia address public wrapperAddress = 0x195f15F2d49d693cE265b4fB0fdDbE15b1850Cc1; constructor() ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(wrapperAddress) {} function requestRandomWords( bool enableNativePayment ) external onlyOwner returns (uint256) { bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: enableNativePayment})); uint256 requestId; uint256 reqPrice; if (enableNativePayment) { (requestId, reqPrice) = requestRandomnessPayInNative(callbackGasLimit, requestConfirmations, numWords, extraArgs); } else { (requestId, reqPrice) = requestRandomness(callbackGasLimit, requestConfirmations, numWords, extraArgs); } s_requests[requestId] = RequestStatus({paid: reqPrice, randomWords: new uint256[](0), fulfilled: false}); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { require(s_requests[_requestId].paid > 0, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); } function getRequestStatus( uint256 _requestId ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].paid > 0, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.paid, request.fulfilled, request.randomWords); } /** * Allow withdraw of Link tokens from the contract */ function withdrawLink() public onlyOwner { LinkTokenInterface link = LinkTokenInterface(linkAddress); require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); } /// @notice withdrawNative withdraws the amount specified in amount to the owner /// @param amount the amount to withdraw, in wei function withdrawNative( uint256 amount ) external onlyOwner { (bool success,) = payable(owner()).call{value: amount}(""); // solhint-disable-next-line gas-custom-errors require(success, "withdrawNative failed"); } event Received(address, uint256); receive() external payable { emit Received(msg.sender, msg.value); } } ``` The parameters define how your requests will be processed. You can find the values for your network in the [Supported networks](/vrf/v2-5/supported-networks) page. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords()` function. It must be less than the `maxGasLimit` limit on the coordinator contract minus the `wrapperGasOverhead`. See the [VRF v2.5 Direct funding limits](/vrf/v2-5/overview/direct-funding#limits) for more details. Adjust this value for larger requests depending on how your `fulfillRandomWords()` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your consuming contract is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` limit on the coordinator contract. - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. The total cost of the callback request depends on how your `fulfillRandomWords()` function processes and stores the received random values, so adjust your `callbackGasLimit` accordingly. The contract includes the following functions: - `requestRandomWords()`: Takes your specified parameters and submits the request to the VRF v2.5 Wrapper contract. - `fulfillRandomWords()`: Receives random values and stores them with your contract. - `getRequestStatus()`: Retrieve request details for a given `_requestId`. - `withdrawLink()`: At any time, the owner of the contract can withdraw the outstanding LINK balance from it. - `withdrawNative()`: At any time, the owner of the contract can withdraw the outstanding native token balance from it. > **NOTE: Security Considerations** > > Be sure to review your contracts to make sure they follow the best practices on the [security > considerations](/vrf/v2-5/security) page. ## Clean up After you are done with this contract, you can retrieve the remaining testnet tokens to use with other examples: ### LINK Call the `withdrawLink()` function. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, the remaining LINK will be transferred from your consuming contract to your wallet address. ### Native tokens Call `getBalance` to retrieve your contract's ETH balance in wei, and then pass that into the `withdrawNative()` function. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, the remaining Sepolia ETH will be transferred from your consuming contract to your wallet address. --- # Subscription Method Source: https://docs.chain.link/vrf/v2/subscription > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). This section explains how to generate random numbers using the subscription method. ## Subscriptions VRF v2 requests receive funding from subscription accounts. The [Subscription Manager](/vrf/v2/subscription/ui) lets you create an account and pre-pay for VRF v2, so you don't provide funding each time your application requests randomness. This reduces the total gas cost to use VRF v2. It also provides a simple way to fund your use of Chainlink products from a single location, so you don't have to manage multiple wallets across several different systems and applications. Subscriptions have the following core concepts: - **Subscription id:** 64-bit unsigned integer representing the unique identifier of the subscription. - **Subscription accounts:** An account that holds LINK tokens and makes them available to fund requests to Chainlink VRF v2 coordinators. - **Subscription owner:** The wallet address that creates and manages a subscription account. Any account can add LINK to the subscription balance, but only the owner can add approved consuming contracts or withdraw funds. - **Consumers:** Consuming contracts that are approved to use funding from your subscription account. - **Subscription balance:** The amount of LINK maintained on your subscription account. Requests from consuming contracts will continue to be funded until the balance runs out, so be sure to maintain sufficient funds in your subscription balance to pay for the requests and keep your applications running. For Chainlink VRF v2 to fulfill your requests, you must maintain a sufficient amount of LINK in your subscription balance. Gas cost calculation includes the following variables: - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. - **Verification gas:** The amount of gas used to verify randomness onchain. The gas price depends on current network conditions. The callback gas depends on your callback function, and the number of random values in your request. The cost of each request is final only after the transaction is complete, but you define the limits you are willing to spend for the request with the following variables: - **Gas lane:** The maximum gas price you are willing to pay for a request in wei. Define this limit by specifying the appropriate `keyHash` in your request. The limits of each gas lane are important for handling gas price spikes when Chainlink VRF bumps the gas price to fulfill your request quickly. - **Callback gas limit:** Specifies the maximum amount of gas you are willing to spend on the callback request. Define this limit by specifying the `callbackGasLimit` value in your request. ## Request and receive data Requests to Chainlink VRF v2 follow the request and receive data cycle. This end-to-end diagram shows each step in the lifecycle of a VRF subscription request, and registering a smart contract with a VRF subscription account: ![Image](/images/vrf/v2-subscription-e2e.webp) Two types of accounts exist in the Ethereum ecosystem, and both are used in VRF: - EOA (Externally Owned Account): An externally owned account that has a private key and can control a smart contract. Transactions can only be initiated by EOAs. - Smart contract: A contract that does not have a private key and executes what it has been designed for as a decentralized application. The Chainlink VRF v2 solution uses both offchain and onchain components: - [VRF v2 Coordinator (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol): A contract designed to interact with the VRF service. It emits an event when a request for randomness is made, and then verifies the random number and proof of how it was generated by the VRF service. - VRF service (offchain component): Listens for requests by subscribing to the VRF Coordinator event logs and calculates a random number based on the block hash and nonce. The VRF service then sends a transaction to the `VRFCoordinator` including the random number and a proof of how it was generated. ### Set up your contract and request Set up your consuming contract: 1. Your contract must inherit [VRFConsumerBaseV2](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol). 2. Your contract must implement the `fulfillRandomWords` function, which is the *callback VRF function*. Here, you add logic to handle the random values after they are returned to your contract. 3. Submit your VRF request by calling `requestRandomWords` of the [VRF Coordinator](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol). Include the following parameters in your request: - `keyHash`: Identifier that maps to a job and a private key on the VRF service and that represents a specified gas lane. If your request is urgent, specify a gas lane with a higher gas price limit. The configuration for your network can be found [here](/vrf/v2/subscription/supported-networks/#configurations). - `s_subscriptionId`: The subscription ID that the consuming contract is registered to. LINK funds are deducted from this subscription. - `requestConfirmations`: The number of block confirmations the VRF service will wait to respond. The minimum and maximum confirmations for your network can be found [here](/vrf/v2/subscription/supported-networks/#configurations). - `callbackGasLimit`: The maximum amount of gas a user is willing to pay for completing the callback VRF function. Note that you cannot put a value larger than maxGasLimit of the VRF Coordinator contract (read [coordinator contract limits](#limits) for more details). - `numWords`: The number of random numbers to request. The maximum random values that can be requested for your network can be found [here](/vrf/v2/subscription/supported-networks/#configurations). ### How VRF processes your request After you submit your request, it is processed using the [Request & Receive Data](#request-and-receive-data) cycle. The VRF coordinator processes the request and determines the final charge to your subscription using the following steps: 1. The VRF coordinator emits an event. 2. The VRF service picks up the event and waits for the specified number of block confirmations to respond back to the VRF coordinator with the random values and a proof (`requestConfirmations`). 3. The VRF coordinator verifies the proof onchain, then it calls back the consuming contract `fulfillRandomWords` function. ## Limits Chainlink VRF v2 has some [subscription limits](#subscription-limits) and [coordinator contract limits](#coordinator-contract-limits). ### Subscription limits Subscriptions are required to maintain a minimum balance, and they can support a limited number of consuming contracts. #### Minimum subscription balance Each subscription must maintain a minimum balance to fund requests from consuming contracts. This minimum balance requirement serves as a buffer against gas volatility by ensuring that all your requests have more than enough funding to go through. If your balance is below the minimum, your requests remain pending for up to 24 hours before they expire. After you add sufficient LINK to a subscription, pending requests automatically process as long as they have not expired. In the Subscription Manager, the minimum subscription balance is displayed as the **Max Cost**, and it indicates the amount of LINK you need to add for a pending request to process. After the request is processed, only the amount actually consumed by the request is deducted from your balance. For example, if your minimum balance is 10 LINK, but your subscription balance is 5 LINK, you need to add at least 5 more LINK for your request to process. This does not mean that your request will ultimately cost 10 LINK. If the request ultimately costs 3 LINK after it has processed, then 3 LINK is deducted from your subscription balance. The minimum subscription balance must be sufficient for each new consuming contract that you add to a subscription. For example, the minimum balance for a subscription that supports 20 consuming contracts needs to cover all the requests for all 20 contracts, while a subscription with one consuming contract only needs to cover that one contract. For one request, the required size of the minimum balance depends on the gas lane and the size of the request. For example, a consuming contract that requests one random value will require a smaller minimum balance than a consuming contract that requests 50 random values. In general, you can estimate the required minimum LINK balance using the following formula where max verification gas is always 200,000 gwei. ``` (((Gas lane maximum * (Max verification gas + Callback gas limit)) / (1,000,000,000 Gwei/ETH)) / (ETH/LINK price)) + LINK premium = Minimum LINK ``` Here is the same formula, broken out into steps: ``` Gas lane maximum * (Max verification gas + Callback gas limit) = Total estimated gas (Gwei) Total estimated gas (Gwei) / 1,000,000,000 Gwei/ETH = Total estimated gas (ETH) Total estimated gas (ETH) / (ETH/LINK price) = Total estimated gas (LINK) Total estimated gas (LINK) + LINK premium = Minimum subscription balance (LINK) ``` #### Maximum consuming contracts Each subscription supports up to 100 consuming contracts. If you need more than 100 consuming contracts, create multiple subscriptions. ### Coordinator contract limits You can see the configuration for each network on the [Supported networks](/vrf/v2/subscription/supported-networks) page. You can also view the full configuration for each coordinator contract directly in Etherscan. As an example, view the [Ethereum Mainnet VRF v2 coordinator contract](https://etherscan.io/token/0x271682DEB8C4E0901D1a1550aD2e64D568E69909#readContract) configuration. - Each coordinator has a `MAX_NUM_WORDS` parameter that limits the maximum number of random values you can receive in each request. - Each coordinator has a `maxGasLimit` parameter, which is the maximum allowed `callbackGasLimit` value for your requests. You must specify a sufficient `callbackGasLimit` to fund the callback request to your consuming contract. This depends on the number of random values you request and how you process them in your `fulfillRandomWords()` function. If your `callbackGasLimit` is not sufficient, the callback fails but your subscription is still charged for the work done to generate your requested random values. --- # Direct Funding Method Source: https://docs.chain.link/vrf/v2/direct-funding > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). This guide explains how to generate random numbers using the *direct funding* method. This method doesn't require a subscription and is optimal for one-off requests for randomness. This method also works best for applications where your end-users must pay the fees for VRF because the cost of the request is determined at request time. ## VRF direct funding Unlike the [subscription method](/vrf/v2/subscription), the direct funding method does not require you to create subscriptions and pre-fund them. Instead, you must directly fund consuming contracts with LINK tokens before they request randomness. Because the consuming contract directly pays the LINK for the request, the cost is calculated during the request and not during the callback when the randomness is fulfilled. Learn [how to estimate costs](/vrf/v2/estimating-costs). ## Request and receive data Requests to Chainlink VRF v2 follow the request and receive data cycle. This end-to-end diagram shows each step in the lifecycle of a VRF direct funding request: ![Image](/images/vrf/v2-direct-funding-e2e.webp) Two types of accounts exist in the Ethereum ecosystem, and both are used in VRF: - EOA (Externally Owned Account): An externally owned account that has a private key and can control a smart contract. Transactions can be initiated only by EOAs. - Smart contract: A smart contract that does not have a private key and executes what it has been designed for as a decentralized application. The Chainlink VRF v2 solution uses both offchain and onchain components: - [VRF v2 Wrapper (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2Wrapper.sol): A wrapper for the VRF Coordinator that provides an interface for consuming contracts. - [VRF v2 Coordinator (onchain component)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol): A contract designed to interact with the VRF service. It emits an event when a request for randomness is made, and then verifies the random number and proof of how it was generated by the VRF service. - VRF service (offchain component): Listens for requests by subscribing to the VRF Coordinator event logs and calculates a random number based on the block hash and nonce. The VRF service then sends a transaction to the `VRFCoordinator` including the random number and a proof of how it was generated. ### Set up your contract and request Set up your consuming contract: 1. Your contract must inherit [VRFV2WrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol). 2. Your contract must implement the `fulfillRandomWords` function, which is the *callback VRF function*. Here, you add logic to handle the random values after they are returned to your contract. 3. Submit your VRF request by calling the `requestRandomness` function in the [VRFV2WrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol) contract. Include the following parameters in your request: - `requestConfirmations`: The number of block confirmations the VRF service will wait to respond. The minimum and maximum confirmations for your network can be found [here](/vrf/v2/direct-funding/supported-networks/#configurations). - `callbackGasLimit`: The maximum amount of gas to pay for completing the callback VRF function. - `numWords`: The number of random numbers to request. You can find the maximum number of random values per request for your network in the [Supported networks](/vrf/v2/direct-funding/supported-networks/#configurations) page. ### How VRF processes your request After you submit your request, it is processed using the [Request & Receive Data](#request-and-receive-data) cycle: 1. The consuming contract calls the [VRFV2Wrapper](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2Wrapper.sol) `calculateRequestPrice` function to estimate the total transaction cost to fulfill randomness. Learn [how to estimate transaction costs](/vrf/v2/estimating-costs). 2. The consuming contract calls the [LinkToken](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol) `transferAndCall` function to pay the wrapper with the calculated request price. This method sends LINK tokens and executes the [VRFV2Wrapper](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2Wrapper.sol) `onTokenTransfer` logic. 3. The VRFV2Wrapper's `onTokenTransfer` logic triggers the [VRF Coordinator](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol) `requestRandomWords` function to request randomness. 4. The VRF coordinator emits an event. 5. The VRF service picks up the event and waits for the specified number of block confirmations to respond back to the VRF coordinator with the random values and a proof (`requestConfirmations`). 6. The VRF coordinator verifies the proof onchain, then it calls back the wrapper contract's `fulfillRandomWords` function. 7. Finally, the VRF Wrapper calls back your consuming contract. ## Limits You can see the configuration for each network on the [Supported networks](/vrf/v2/direct-funding/supported-networks) page. You can also view the full configuration for each VRF v2 Wrapper contract directly in Etherscan. As an example, view the [Ethereum Mainnet VRF v2 Wrapper contract](https://etherscan.io/address/0x5A861794B927983406fCE1D062e00b9368d97Df6#readContract) configuration by calling `getConfig` function. - Each wrapper has a `maxNumWords` parameter that limits the maximum number of random values you can receive in each request. - The maximum allowed `callbackGasLimit` value for your requests is defined in the [Coordinator contract supported networks](/vrf/v2/subscription/supported-networks) page. Because the VRF v2 Wrapper adds an overhead, your `callbackGasLimit` must not exceed `maxGasLimit - wrapperGasOverhead`. Learn more about [estimating costs](/vrf/v2/estimating-costs). --- # Chainlink VRF API Reference [v1] Source: https://docs.chain.link/vrf/v1/api-reference > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). API reference for [`VRFConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFConsumerBase.sol). ## Index ### Constructors | Name | Description | | --------------------------- | ----------------------------------- | | [constructor](#constructor) | Initialize your consuming contract. | ### Functions | Name | Description | | --------------------------------------- | ------------------------------------------------------------ | | [requestRandomness](#requestrandomness) | Make a request to the VRFCoordinator. | | [fulfillRandomness](#fulfillrandomness) | Called by VRFCoordinator when it receives a valid VRF proof. | *** ## Constructor Initialize your consuming contract. ```solidity constructor(address _vrfCoordinator, address _link) ``` - `_vrfCoordinator`: Address of the Chainlink VRF Coordinator. See [Chainlink VRF Addresses](/vrf/v1/supported-networks) for details. - `_link`: Address of the LINK token. See [LINK Token Addresses](/resources/link-token-contracts) for details. *** > Note: `_seed` has recently been deprecated. ## Functions ### requestRandomness Make a request to the VRF coordinator. ```solidity function requestRandomness(bytes32 _keyHash, uint256 _fee) public returns (bytes32 requestId) ``` - `_keyHash`: The public key against which randomness is generated. See [Chainlink VRF supported networks](/vrf/v1/supported-networks) for details. - `_fee`: The fee, in LINK, for the request. Specified by the oracle. - `RETURN`: The ID unique to a single request. ### fulfillRandomness Called by VRFCoordinator when it receives a valid VRF proof. Override this function to act upon the random number generated by Chainlink VRF. ```solidity function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual; ``` - `requestId`: The ID initially returned by `requestRandomness`. - `randomness`: The random number generated by Chainlink VRF. ## Reference ### Maximizing security Chainlink VRF provides powerful security guarantees and is easy to integrate. However, smart contract security is a nuanced topic. You can read about the [top security considerations for VRF](/vrf/v1/security). --- # VRF Best Practices [v1] Source: https://docs.chain.link/vrf/v1/best-practices > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). Below are the best practices for using Chainlink VRF. ## Getting a random number within a range If you need to generate a random number within a given range, you use [modulo](https://docs.soliditylang.org/en/v0.8.17/types.html#modulo) to define the limits of your range. Below you can see how to get a random number between 1 and 50. ```solidity uint256 public randomResult; function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { randomResult = (randomness % 50) + 1; } ``` ## Getting multiple random numbers If you want to get multiple random numbers from a single VRF response, you should create an array where the `randomValue` is your original returned VRF number and `n` is the desired number of random numbers. ```solidity function expand(uint256 randomValue, uint256 n) public pure returns (uint256[] memory expandedValues) { expandedValues = new uint256[](n); for (uint256 i = 0; i < n; i++) { expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i))); } return expandedValues; } ``` ## Having multiple VRF requests in flight If you want to have multiple VRF requests in flight, you might want to create a mapping between the `requestId` and the address of the requester. ```solidity mapping(bytes32 => address) public requestIdToAddress; function getRandomNumber() public returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); bytes32 requestId = requestRandomness(keyHash, fee); requestIdToAddress[requestId] = msg.sender; } function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { address requestAddress = requestIdToAddress[requestId]; } ``` If you want to keep order when a request was made, you might want to use a mapping of `requestId` to the index/order of this request. ```solidity mapping(bytes32 => uint256) public requestIdToRequestNumberIndex; uint256 public requestCounter; function getRandomNumber() public returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); bytes32 requestId = requestRandomness(keyHash, fee); requestIdToRequestNumberIndex[requestId] = requestCounter; requestCounter += 1; } function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { uint256 requestNumber = requestIdToRequestNumberIndex[requestId]; } ``` If you want to keep generated random numbers of several VRF requests, you might want to use a mapping of `requestId` to the returned random number. ```solidity mapping(bytes32 => uint256) public requestIdToRandomNumber; function getRandomNumber() public returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); return requestRandomness(keyHash, fee); } function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { requestIdToRandomNumber[requestId] = randomness; } ``` Feel free to use whatever data structure you prefer. --- # Get a Random Number [v1] Source: https://docs.chain.link/vrf/v1/examples/get-a-random-number > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). This page explains how to get a random number inside a smart contract using Chainlink VRF. ## Random Number Consumer Chainlink VRF follows the [Request & Receive Data](/any-api/introduction) cycle. To consume randomness, your contract should inherit from [VRFConsumerBase](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFConsumerBase.sol) and define two required functions: - `requestRandomness`, which makes the initial request for randomness. - `fulfillRandomness`, which is the function that receives and does something with verified randomness. The contract should own enough LINK to pay the specified fee. The beginner walkthrough explains how to [fund your contract](/resources/fund-your-contract). Note, the below values have to be configured correctly for VRF requests to work. You can find the respective values for your network in the [VRF Contracts page](/vrf/v1/supported-networks). - `LINK Token` - LINK token address on the corresponding network (Ethereum, Polygon, BSC, etc) - `VRF Coordinator` - address of the Chainlink VRF Coordinator - `Key Hash` - public key against which randomness is generated - `Fee` - fee required to fulfill a VRF request > **TIP: Security Considerations** > > Be sure to look your contract over with [these security considerations](/vrf/v1/security) in mind! > **NOTE: Remember to fund your contract with LINK!** > > Requesting randomness will fail unless your deployed contract has enough LINK to pay for it. **Learn how to [Acquire > testnet LINK](/resources/acquire-link) and [Fund your contract](/resources/fund-your-contract)**. ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import {VRFConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ contract RandomNumberConsumer is VRFConsumerBase { event RequestFulfilled(bytes32 requestId, uint256 randomness); bytes32 internal keyHash; uint256 internal fee; uint256 public randomResult; /** * Constructor inherits VRFConsumerBase * * Network: Sepolia * Chainlink VRF Coordinator address: 0x271682DEB8C4E0901D1a1550aD2e64D568E69909 * LINK token address: 0x779877A7B0D9E8603169DdbD7836e478b4624789 * Key Hash: 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c */ constructor() VRFConsumerBase( 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625, // VRF Coordinator 0x779877A7B0D9E8603169DdbD7836e478b4624789 // LINK Token ) { keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; fee = 0.1 * 10 ** 18; // 0.1 LINK (Varies by network) } /** * Requests randomness */ function getRandomNumber() public returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); return requestRandomness(keyHash, fee); } /** * Callback function used by VRF Coordinator */ function fulfillRandomness( bytes32 requestId, uint256 randomness ) internal override { randomResult = randomness; emit RequestFulfilled(requestId, randomness); } // function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract } ``` > **NOTE: Maximum Gas for Callback** > > If your `fulfillRandomness` function uses more than 200k gas, the transaction will fail. ## Getting More Randomness If you are looking for how to turn a single result into multiple random numbers, check out our guide on [Randomness Expansion](/vrf/v1/best-practices/#getting-multiple-random-numbers). ## Network Congestion and Responsiveness Network congestion can occur on all blockchains from time to time, which may result in transactions taking longer to get included in a block. During times of network congestion, the VRF service will continue responding to randomness requests, but fulfillment response times will corresponding increase based on the level of congestion. It is important you account for this in your use case and set expectations accordingly. --- # Introduction to Chainlink VRF [v1] Source: https://docs.chain.link/vrf/v1/introduction > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). ## Generate Random Numbers in your Smart Contracts Chainlink VRF (Verifiable Random Function) is a provably-fair and verifiable source of randomness designed for smart contracts. Smart contract developers can use Chainlink VRF as a tamper-proof random number generator (RNG) to build reliable smart contracts for any applications which rely on unpredictable outcomes: - Blockchain games and NFTs - Random assignment of duties and resources (e.g. randomly assigning judges to cases) - Choosing a representative sample for consensus mechanisms Learn how to write smart contracts that consume random numbers: [Get a Random Number](/vrf/v1/examples/get-a-random-number). ## onchain Verification of Randomness Chainlink VRF enables smart contracts to access randomness without compromising on security or usability. With every new request for randomness, Chainlink VRF generates a random number and cryptographic proof of how that number was determined. The proof is published and verified onchain before it can be used by any consuming applications. This process ensures that the results cannot be tampered with nor manipulated by anyone, including oracle operators, miners, users and even smart contract developers. Read more about Chainlink VRF in [our announcement post](https://blog.chain.link/verifiable-random-functions-vrf-random-number-generation-rng-feature/). --- # VRF Security Considerations [v1] Source: https://docs.chain.link/vrf/v1/security > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). Gaining access to high quality randomness onchain requires a solution like Chainlink's VRF, but it also requires you to understand some of the ways that randomness generation can be manipulated by miners/validators. Here are some of the top security considerations you should review in your project. - [Use `requestId` to match randomness requests with their fulfillment in order](#use-requestid-to-match-randomness-requests-with-their-fulfillment-in-order) - [Choose a safe block confirmation time, which will vary between blockchains](#choose-a-safe-block-confirmation-time-which-will-vary-between-blockchains) - [Do not allow re-requesting or cancellation of randomness](#do-not-allow-re-requesting-or-cancellation-of-randomness) - [Don't accept bids/bets/inputs after you have made a randomness request](#dont-accept-bidsbetsinputs-after-you-have-made-a-randomness-request) - [`fulfillRandomness` must not revert](#fulfillrandomness-must-not-revert) - [Use `VRFConsumerBase` in your contract, to interact with the VRF service](#use-vrfconsumerbase-in-your-contract-to-interact-with-the-vrf-service) ## Use `requestId` to match randomness requests with their fulfillment in order If your contract could have multiple VRF requests in flight simultaneously, you must ensure that the order in which the VRF fulfillments arrive cannot be used to manipulate your contract's user-significant behavior. Blockchain miners/validators can control the order in which your requests appear onchain, and hence the order in which your contract responds to them. For example, if you made randomness requests `A`, `B`, `C` in short succession, there is no guarantee that the associated randomness fulfillments will also be in order `A`, `B`, `C`. The randomness fulfillments might just as well arrive at your contract in order `C`, `A`, `B` or any other order. We recommend using the `requestID` to match randomness requests with their corresponding fulfillments. ## Choose a safe block confirmation time, which will vary between blockchains In principle, miners and validators of your underlying blockchain could rewrite the chain's history to put a randomness request from your contract into a different block, which would result in a different VRF output. Note that this does not enable a miner to determine the random value in advance. It only enables them to get a fresh random value that may or not be to their advantage. By way of analogy, they can only re-roll the dice, not predetermine or predict which side it will land on. You must choose an appropriate confirmation time for the randomness requests you make (i.e. how many blocks the VRF service waits before writing a fulfillment to the chain) to make such rewrite attacks unprofitable in the context of your application and its value-at-risk. On proof-of-stake blockchains (e.g. BSC, Polygon), what block confirmation time is considered secure depends on the specifics of their consensus mechanism and whether you're willing to trust any underlying assumptions of (partial) honesty of validators. For further details, take a look at the consensus documentation for the chain you want to use: - [Ethereum Consensus Mechanisms](https://ethereum.org/en/developers/docs/consensus-mechanisms/) - [BNB Chain Consensus Docs](https://docs.binance.org/smart-chain/guides/concepts/consensus.html) - [Polygon Consensus Docs](https://docs.polygon.technology/pos/architecture/bor/?h=consensus) Understanding the blockchains you build your application on is very important. You should take time to understand [chain reorganization](https://blog.ethereum.org/2015/08/08/chain-reorganisation-depth-expectations/) which will also result in a different VRF output, which could be exploited. ## Do not allow re-requesting or cancellation of randomness Any re-request or cancellation of randomness is an incorrect use of VRF. dApps that implement the ability to cancel or re-request randomness for specific commitments must consider the additional attack vectors created by this capability. For example, you must prevent the ability for any party to discard unfavorable randomness. ## Don't accept bids/bets/inputs after you have made a randomness request Consider the example of a contract that mints a random NFT in response to a users' actions. The contract should: 1. record whatever actions of the user may affect the generated NFT 2. **stop accepting further user actions that may affect the generated NFT** and issue a randomness request 3. on randomness fulfillment, mint the NFT Generally speaking, whenever an outcome in your contract depends on some user-supplied inputs and randomness, the contract should not accept any additional user-supplied inputs once the randomness request has been issued. Otherwise, the cryptoeconomic security properties may be violated by an attacker that can rewrite the chain. ## `fulfillRandomness` must not revert If your fulfillRandomness implementation reverts, the VRF service will not attempt to call it a second time. Make sure your contract logic does not revert. Consider simply storing the randomness and taking more complex follow-on actions in separate contract calls made by you or your users. ## Use `VRFConsumerBase` in your contract, to interact with the VRF service `VRFConsumerBase` tracks important state which needs to be synchronized with the `VRFCoordinator` state. Some users fold `VRFConsumerBase` into their own contracts, but this means taking on significant extra complexity, so we advise against doing so. Along the same lines, don't override `rawFulfillRandomness`. --- # Chainlink VRF Supported Networks [v1] Source: https://docs.chain.link/vrf/v1/supported-networks > **CAUTION: Migrate to VRF V2.5** > > VRF V2.5 replaces both VRF V1 and VRF V2 on November 29, 2024. [Migrate to VRF V2.5](/vrf/v2-5/migration-from-v1). Chainlink VRF allows you to integrate provably-fair and verifiably random data in your smart contract. For implementation details, read [Introduction to Chainlink VRF](/vrf/v1/introduction). > **CAUTION: Understand Risks associated with Bridges** > > If you are using a cross-chain bridge to transfer your LINK tokens, read the [Bridges and Associated Risks](/resources/bridge-risks) guide to understand what cross-chain bridges are and the risks associated with using them. ## Polygon Mainnet > **TIP: Important** > > The LINK provided by the [Polygon Bridge](https://wallet.polygon.technology/bridge) is not ERC-677 compatible, so > cannot be used with Chainlink oracles. However, it can be [**converted to the official LINK token on Polygon using > Chainlink's PegSwap service**](https://pegswap.chain.link/) | Item | Value | | --------------- | -------------------------------------------------------------------- | | LINK Token | `0xb0897686c545045aFc77CF20eC7A532E3120E0F1` | | VRF Coordinator | `0x3d2341ADb2D31f1c5530cDC622016af293177AE0` | | Key Hash | `0xf86195cf7690c55907b2b611ebb7343a6f649bff128701cc542f0569e2c549da` | | Fee | 0.0001 LINK | > **NOTE: VRF Response Times on Polygon** > > VRF responses are generated after 10 block confirmations on Polygon by default. ## BNB Chain Mainnet > **NOTE: Important** > > The LINK provided by the [BNB Chain Bridge](https://www.bnbchain.world/en/bridge) is not ERC-677 compatible, so cannot > be used with Chainlink oracles. However, it can be [**converted to the official LINK token on BNB Chain using > Chainlink's PegSwap service**](https://pegswap.chain.link/). | Item | Value | | --------------- | ------------------------------------------------------------------------------------ | | LINK Token | `0x404460C6A5EdE2D891e8297795264fDe62ADBB75` | | VRF Coordinator | `0x747973a5A2a4Ae1D3a8fDF5479f1514F65Db9C31` | | Key Hash | `0xc251acd21ec4fb7f31bb8868288bfdbaeb4fbfec2df3735ddbd4f7dc8d60103c` | | Fee | 0.2 LINK - initial fees on BNB Chain are meant to cover the highest gas cost prices. | ## BNB Chain Testnet > **NOTE: BNB Chain Faucet** > > Testnet LINK is available from [https://faucets.chain.link/bnb-chain-testnet](https://faucets.chain.link/bnb-chain-testnet) | Item | Value | | --------------- | --------------------------------------------------------------------- | | LINK | `0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06` | | VRF Coordinator | `0xa555fC018435bef5A13C6c6870a9d4C11DEC329C ` | | Key Hash | `0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186 ` | | Fee | 0.1 LINK | ## Ethereum Mainnet | Item | Value | | --------------- | --------------------------------------------------------------------------------- | | LINK Token | `0x514910771AF9Ca656af840dff83E8264EcF986CA` | | VRF Coordinator | `0xf0d54349aDdcf704F77AE15b96510dEA15cb7952` | | Key Hash | `0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445` | | Fee | 2 LINK - initial fees on Ethereum are meant to cover the highest gas cost prices. | --- # VRF V2 Best Practices Source: https://docs.chain.link/vrf/v2/best-practices > **TIP: VRF V2.5 Best Practices** > > Refer to the [VRF V2.5 Best Practices page](/vrf/v2-5/best-practices) for VRF best practices with updated VRF 2.5 code > examples. These are example best practices for using Chainlink VRF. To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Getting a random number within a range If you need to generate a random number within a given range, use [modulo](https://docs.soliditylang.org/en/v0.8.7/types.html#modulo) to define the limits of your range. Below you can see how to get a random number in a range from 1 to 50. ```solidity function fulfillRandomWords( uint256, /* requestId */ uint256[] memory randomWords ) internal override { // Assuming only one random word was requested. s_randomRange = (randomWords[0] % 50) + 1; } ``` ## Getting multiple random values If you want to get multiple random values from a single VRF request, you can request this directly with the `numWords` argument: - If you are using the VRF v2 subscription method, see the [Get a Random Number](/vrf/v2/subscription/examples/get-a-random-number) guide for an example where one request returns multiple random values. - If you are using the VRF v2 direct funding method, see the [Get a Random Number](/vrf/v2/direct-funding/examples/get-a-random-number) guide for an example where one request returns multiple random values. ## Processing simultaneous VRF requests If you want to have multiple VRF requests processing simultaneously, create a mapping between `requestId` and the response. You might also create a mapping between the `requestId` and the address of the requester to track which address made each request. ```solidity mapping(uint256 => uint256[]) public s_requestIdToRandomWords; mapping(uint256 => address) public s_requestIdToAddress; uint256 public s_requestId; function requestRandomWords() external onlyOwner returns (uint256) { uint256 requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); s_requestIdToAddress[requestId] = msg.sender; // Store the latest requestId for this example. s_requestId = requestId; // Return the requestId to the requester. return requestId; } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { // You can return the value to the requester, // but this example simply stores it. s_requestIdToRandomWords[requestId] = randomWords; } ``` You could also map the `requestId` to an index to keep track of the order in which a request was made. ```solidity mapping(uint256 => uint256) s_requestIdToRequestIndex; mapping(uint256 => uint256[]) public s_requestIndexToRandomWords; uint256 public requestCounter; function requestRandomWords() external onlyOwner { uint256 requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); s_requestIdToRequestIndex[requestId] = requestCounter; requestCounter += 1; } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { uint256 requestNumber = s_requestIdToRequestIndex[requestId]; s_requestIndexToRandomWords[requestNumber] = randomWords; } ``` ## Processing VRF responses through different execution paths If you want to process VRF responses depending on predetermined conditions, you can create an `enum`. When requesting for randomness, map each `requestId` to an enum. This way, you can handle different execution paths in `fulfillRandomWords`. See the following example: ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. // It shows how to setup multiple execution paths for handling a response. pragma solidity ^0.8.7; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract VRFv2MultiplePaths is VRFConsumerBaseV2 { VRFCoordinatorV2Interface COORDINATOR; // Your subscription ID. uint64 s_subscriptionId; // Sepolia coordinator. For other networks, // see https://docs.chain.link/docs/vrf/v2/supported-networks/#configurations address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2/supported-networks/#configurations bytes32 keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; uint32 callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 1 random value in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 numWords = 1; enum Variable { A, B, C } uint256 public variableA; uint256 public variableB; uint256 public variableC; mapping(uint256 => Variable) public requests; // events event FulfilledA(uint256 requestId, uint256 value); event FulfilledB(uint256 requestId, uint256 value); event FulfilledC(uint256 requestId, uint256 value); constructor( uint64 subscriptionId ) VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_subscriptionId = subscriptionId; } function updateVariable( uint256 input ) public { uint256 requestId = COORDINATOR.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords); if (input % 2 == 0) { requests[requestId] = Variable.A; } else if (input % 3 == 0) { requests[requestId] = Variable.B; } else { requests[requestId] = Variable.C; } } function fulfillRandomWords( uint256 requestId, uint256[] memory randomWords ) internal override { Variable variable = requests[requestId]; if (variable == Variable.A) { fulfillA(requestId, randomWords[0]); } else if (variable == Variable.B) { fulfillB(requestId, randomWords[0]); } else if (variable == Variable.C) { fulfillC(requestId, randomWords[0]); } } function fulfillA( uint256 requestId, uint256 randomWord ) private { // execution path A variableA = randomWord; emit FulfilledA(requestId, randomWord); } function fulfillB( uint256 requestId, uint256 randomWord ) private { // execution path B variableB = randomWord; emit FulfilledB(requestId, randomWord); } function fulfillC( uint256 requestId, uint256 randomWord ) private { // execution path C variableC = randomWord; emit FulfilledC(requestId, randomWord); } } ``` --- # Get a Random Number with VRF V2 Source: https://docs.chain.link/vrf/v2/direct-funding/examples/get-a-random-number This guide explains how to get random values using a simple contract to request and receive random values from Chainlink VRF v2 without managing a subscription. To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Requirements This guide assumes that you know how to create and deploy smart contracts on Ethereum testnets using the following tools: - [The Remix IDE](https://remix.ethereum.org/) - [MetaMask](https://metamask.io/) - [Sepolia testnet ETH](/resources/link-token-contracts/#sepolia-testnet) If you are new to developing smart contracts on Ethereum, see the [Getting Started](/getting-started/conceptual-overview) guide to learn the basics. ## Create and deploy a VRF v2 compatible contract For this example, use the [VRFv2DirectFundingConsumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2DirectFundingConsumer.sol) sample contract. This contract imports the following dependencies: - `VRFV2WrapperConsumerBase.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol) - `ConfirmedOwner.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/access/ConfirmedOwner.sol) The contract also includes pre-configured values for the necessary request parameters such as `callbackGasLimit`, `requestConfirmations`, the number of random words `numWords`, the VRF v2 Wrapper address `wrapperAddress`, and the LINK token address `linkAddress`. You can change these parameters if you want to experiment on different testnets. Build and deploy the contract on Sepolia. 1. Open the [`VRFv2DirectFundingConsumer.sol` contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2DirectFundingConsumer.sol) in Remix. [Open VRFv2DirectFundingConsumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2DirectFundingConsumer.sol) 2. On the **Compile** tab in Remix, compile the `VRFv2DirectFundingConsumer` contract. 3. Configure your deployment. On the **Deploy** tab in Remix, select the **Injected Web3 Environment** and select the `VRFv2DirectFundingConsumer` contract from the contract list. 4. Click the **Deploy** button to deploy your contract onchain. MetaMask opens and asks you to confirm the transaction. 5. After you deploy your contract, copy the address from the **Deployed Contracts** list in Remix. Before you can request randomness from VRF v2, you must fund your consuming contract with enough LINK tokens in order to request for randomness. Next, [fund your contract](#fund-your-contract). ## Fund Your Contract Requests for randomness will fail unless your consuming contract has enough LINK. 1. [Acquire testnet LINK](/resources/acquire-link). 2. [Fund your contract with testnet LINK](/resources/fund-your-contract). For this example, funding your contract with 2 LINK should be sufficient. ## Request random values The deployed contract requests random values from Chainlink VRF, receives those values, builds a struct `RequestStatus` containing them, and stores the struct in a mapping `s_requests`. Run the `requestRandomWords()` function on your contract to start the request. 1. Return to Remix and view your deployed contract functions in the **Deployed Contracts** list. 2. Click the `requestRandomWords()` function to send the request for random values to Chainlink VRF. MetaMask opens and asks you to confirm the transaction. > **NOTE: Set your gas limit in MetaMask** > > Remix IDE doesn't set the right gas limit, so you must [edit the > gas limit in MetaMask](https://support.metamask.io/hc/en-us/articles/360022895972) within the **Advanced gas controls** settings. > > For this example to work, set the gas limit to *400,000* in MetaMask. > > First, [enable **Advanced gas controls** in your MetaMask settings](https://support.metamask.io/hc/en-us/articles/360022895972). > > Before confirming your transaction in MetaMask, navigate to the screen where you can edit the gas limit: Select **Site suggested** > **Advanced** > **Advanced gas controls** and select **Edit** next to the **Gas limit** amount. Update the **Gas limit** value to *400000* and select **Save**. Finally, confirm the transaction. After you approve the transaction, Chainlink VRF processes your request. Chainlink VRF fulfills the request and returns the random values to your contract in a callback to the `fulfillRandomWords()` function. At this point, a new key `requestId` is added to the mapping `s_requests`. Depending on current testnet conditions, it might take a few minutes for the callback to return the requested random values to your contract. 3. To fetch the request ID of your request, call `lastRequestId()`. 4. After the oracle returns the random values to your contract, the mapping `s_requests` is updated. The received random values are stored in `s_requests[_requestId].randomWords`. 5. Call `getRequestStatus()` and specify the `requestId` to display the random words. > **NOTE: Note on Requesting or Cancelling Randomness** > > Do not allow re-requesting or cancellation of randomness. For more information, see the [VRF Security > Considerations](/vrf/v2/security#do-not-allow-re-requesting-or-cancellation-of-randomness) page. ## Analyzing the contract In this example, the consuming contract uses static configuration parameters. ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity ^0.8.7; import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {VRFV2WrapperConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract VRFv2DirectFundingConsumer is VRFV2WrapperConsumerBase, ConfirmedOwner { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); struct RequestStatus { uint256 paid; // amount paid in link bool fulfilled; // whether the request has been successfully fulfilled uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFV2Wrapper.getConfig().maxNumWords. uint32 numWords = 2; // Address LINK - hardcoded for Sepolia address linkAddress = 0x779877A7B0D9E8603169DdbD7836e478b4624789; // address WRAPPER - hardcoded for Sepolia address wrapperAddress = 0xab18414CD93297B0d12ac29E63Ca20f515b3DB46; constructor() ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(linkAddress, wrapperAddress) {} function requestRandomWords() external onlyOwner returns (uint256 requestId) { requestId = requestRandomness(callbackGasLimit, requestConfirmations, numWords); s_requests[requestId] = RequestStatus({ paid: VRF_V2_WRAPPER.calculateRequestPrice(callbackGasLimit), randomWords: new uint256[](0), fulfilled: false }); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { require(s_requests[_requestId].paid > 0, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); } function getRequestStatus( uint256 _requestId ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].paid > 0, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.paid, request.fulfilled, request.randomWords); } /** * Allow withdraw of Link tokens from the contract */ function withdrawLink() public onlyOwner { LinkTokenInterface link = LinkTokenInterface(linkAddress); require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); } } ``` The parameters define how your requests will be processed. You can find the values for your network in the [Supported networks](/vrf/v2/direct-funding/supported-networks) page. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords()` function. It must be less than the `maxGasLimit` limit on the coordinator contract minus the `wrapperGasOverhead`. See the [VRF v2 Direct funding limits](/vrf/v2/direct-funding/#limits) for more details. Adjust this value for larger requests depending on how your `fulfillRandomWords()` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your consuming contract is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` limit on the coordinator contract. - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. The total cost of the callback request depends on how your `fulfillRandomWords()` function processes and stores the received random values, so adjust your `callbackGasLimit` accordingly. The contract includes the following functions: - `requestRandomWords()`: Takes your specified parameters and submits the request to the VRF v2 Wrapper contract. - `fulfillRandomWords()`: Receives random values and stores them with your contract. - `getRequestStatus()`: Retrieve request details for a given `_requestId`. - `withdrawLink()`: At any time, the owner of the contract can withdraw outstanding LINK balance from it. > **NOTE: Security Considerations** > > Be sure to review your contracts to make sure they follow the best practices on the [security > considerations](/vrf/v2/security) page. ## Clean up After you are done with this contract, you can retrieve the remaining testnet LINK to use with other examples. 1. Call `withdrawLink()` function. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, the remaining LINK will be transferred from your consuming contract to your wallet address. --- # Local testing using a Mock contract Source: https://docs.chain.link/vrf/v2/direct-funding/examples/test-locally This guide explains how to test Chainlink VRF v2 on a [Remix IDE](https://remix-ide.readthedocs.io/en/latest/run.html#environment) sandbox blockchain environment. **Note**: You can reuse the same logic on another development environment, such as Hardhat or Truffle. For example, read the Hardhat Starter Kit [RandomNumberDirectFundingConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberDirectFundingConsumer.spec.js). > **CAUTION: Test on public testnets thoroughly** > > Even though local testing has several benefits, testing with a VRF mock covers the bare minimum of use cases. Make > sure to test your consumer contract thoroughly on public testnets. ## Benefits of local testing ## Testing logic Complete the following tasks to test your VRF v2 consumer locally: 1. Deploy the [VRFCoordinatorV2Mock](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol). This contract is a mock of the [VRFCoordinatorV2](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol) contract. 2. Deploy the [MockV3Aggregator](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/tests/MockV3Aggregator.sol) contract. 3. Deploy the [LinkToken](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol) contract. 4. Deploy the [VRFV2Wrapper](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2Wrapper.sol) contract. 5. Call the VRFV2Wrapper [setConfig function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFV2Wrapper.sol#L119) to set wrapper specific parameters. 6. Fund the VRFv2Wrapper subscription. 7. Call the VRFCoordinatorV2Mock [addConsumer function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L230) to add the wrapper contract to your subscription. 8. Deploy your VRF consumer contract. 9. Fund your consumer contract with LINK tokens. 10. Request random words from your consumer contract. 11. Call the VRFCoordinatorV2Mock [fulfillRandomWords function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L108) to fulfill your consumer contract request. ## Prerequisites This guide will require you to finetune the gas limit when fulfilling requests. When writing, manually setting up the gas limits on RemixIDE is not supported, so you will use RemixIDE in conjunction with [Metamask](https://metamask.io/). [Ganache](https://trufflesuite.com/ganache/) lets you quickly fire up a personal Ethereum blockchain. If you still need to install Ganache, follow the [official guide](https://trufflesuite.com/docs/ganache/quickstart/). 1. Once Ganache is installed, click the *QUICKSTART* button to start a local Ethereum node. ![Image](/images/vrf/mock/ganache.jpg) **Note**: Make sure to note the RPC server. In this example, the RPC server is *[http://127.0.0.1:7545/](http://127.0.0.1:7545/)*. 2. Follow the Metamask [official guide](https://support.metamask.io/hc/en-us/articles/360043227612-How-to-add-a-custom-network-RPC#h_01G63GGJ83DGDRCS2ZWXM37CV5) to add a custom network manually. ![Image](/images/vrf/mock/metamaskcustomnetwork.jpg) 3. Import a Ganache account into Metamask. 1. On Ganache, click on the *key* symbol of the first account: ![Image](/images/vrf/mock/ganacheshowkeys.jpg) 2. Copy the private key: ![Image](/images/vrf/mock/ganacheprivatekey.jpg) 3. Follow the Metamask [official guide](https://support.metamask.io/hc/en-us/articles/360015489331-How-to-import-an-account) to import an account using a private key. 4. Your Metamask is connected to *Ganache*, and you should have access to the newly imported account. ![Image](/images/vrf/mock/metamaskganacheaccount.jpg) ## Testing ### Open the contracts on RemixIDE Open *VRFCoordinatorV2Mock* and compile in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol"; ``` Open *MockV3Aggregator* and compile in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/shared/mocks/MockV3Aggregator.sol"; ``` Open *LinkToken* and compile in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol"; ``` Open *VRFV2Wrapper* and compile in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.6; import "@chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol"; ``` Open *RandomNumberDirectFundingConsumerV2* and compile in Remix: ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that directly pays for each request. pragma solidity ^0.8.7; import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {VRFV2WrapperConsumerBase} from "@chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UNAUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract RandomNumberDirectFundingConsumerV2 is VRFV2WrapperConsumerBase, ConfirmedOwner { event RequestSent(uint256 requestId, uint32 numWords, uint256 paid); event RequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); error InsufficientFunds(uint256 balance, uint256 paid); error RequestNotFound(uint256 requestId); error LinkTransferError(address sender, address receiver, uint256 amount); struct RequestStatus { uint256 paid; // amount paid in link bool fulfilled; // whether the request has been successfully fulfilled uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // configuration: https://docs.chain.link/vrf/v2/direct-funding/supported-networks#configurations constructor( address _linkAddress, address _wrapperAddress ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_linkAddress, _wrapperAddress) {} // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. // The default is 3, but you can set this higher. // For this example, retrieve 2 random values in one request. // Cannot exceed VRFV2Wrapper.getConfig().maxNumWords. function requestRandomWords( uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords ) external onlyOwner returns (uint256 requestId) { requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); uint256 balance = LINK.balanceOf(address(this)); if (balance < paid) revert InsufficientFunds(balance, paid); s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false}); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, _numWords, paid); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { RequestStatus storage request = s_requests[_requestId]; if (request.paid == 0) revert RequestNotFound(_requestId); request.fulfilled = true; request.randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords, request.paid); } function getNumberOfRequests() external view returns (uint256) { return requestIds.length; } function getRequestStatus( uint256 _requestId ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { RequestStatus memory request = s_requests[_requestId]; if (request.paid == 0) revert RequestNotFound(_requestId); return (request.paid, request.fulfilled, request.randomWords); } /** * Allow withdraw of Link tokens from the contract */ function withdrawLink( address _receiver ) public onlyOwner { bool success = LINK.transfer(_receiver, LINK.balanceOf(address(this))); if (!success) { revert LinkTransferError(msg.sender, _receiver, LINK.balanceOf(address(this))); } } } ``` Your RemixIDE file explorer should display the opened contracts: ![Image](/images/vrf/mock/v2-df-remix-fileexplorer.jpg) ### Select the correct RemixIDE environment Under *DEPLOY & RUN TRANSACTIONS*: 1. Set the Environment to *Injected Provider - Metamask*: ![Image](/images/vrf/mock/injectedmetamask.jpg) 2. On Metamask, connect your Ganache account to the Remix IDE. ![Image](/images/vrf/mock/ganacheremixconnect.jpg) 3. Click on Connect. The RemixIDE environment should be set to the correct environment, and the account should be the Ganache account. ![Image](/images/vrf/mock/remixenvinjected.jpg) ### Deploy VRFCoordinatorV2Mock 1. Open *VRFCoordinatorV2Mock.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *VRFCoordinatorV2Mock*. ![Image](/images/vrf/mock/v2-deploymockdf.jpg) 3. Under *DEPLOY*, fill in the `_BASEFEE` and `_GASPRICELINK`. These variables are used in the *VRFCoordinatorV2Mock* contract to represent the base fee and the gas price (in LINK tokens) for the VRF requests. You can set: `_BASEFEE=100000000000000000` and `_GASPRICELINK=1000000000`. 4. Click on *transact* to deploy the *VRFCoordinatorV2Mock* contract. 5. A Metamask popup will open. Click on *Confirm*. 6. Once deployed, you should see the *VRFCoordinatorV2Mock* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedmockdf.jpg) 7. Note the address of the deployed contract. ### Deploy MockV3Aggregator The *MockV3Aggregator* contract is designed for testing purposes, allowing you to simulate an oracle price feed without interacting with the existing Chainlink network. 1. Open *MockV3Aggregator.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *MockV3Aggregator*. ![Image](/images/vrf/mock/v2-deployaggregatormock.jpg) 3. Under *DEPLOY*, fill in `_DECIMALS` and `_INITIALANSWER`. These variables are used in the *MockV3Aggregator* contract to represent the number of decimals the aggregator's answer should have and the most recent price feed answer. You can set: `_DECIMALS=18` and `_INITIALANSWER=3000000000000000` (We are considering that `1 LINK = 0.003 native gas tokens`). 4. Click on *transact* to deploy the *MockV3Aggregator* contract. 5. A Metamask popup will open. Click on *Confirm*. 6. Once deployed, you should see the *MockV3Aggregator* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedaggregatormock.jpg) 7. Note the address of the deployed contract. ### Deploy LinkToken The Chainlink VRF v2 direct funding method requires your consumer contract to pay for VRF requests in LINK. Therefore, you have to deploy the *LinkToken* contract to your local blockchain. 1. Open *LinkToken.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *LinkToken*. ![Image](/images/vrf/mock/v2-deploylink.jpg) 3. Under *DEPLOY*, click on *transact* to deploy the *LinkToken* contract. 4. A Metamask popup will open. Click on *Confirm*. 5. Once deployed, you should see the *LinkToken* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedlink.jpg) 6. Note the address of the deployed contract. ### Deploy VRFV2Wrapper As the VRF v2 direct funding [end-to-end diagram](/vrf/v2/direct-funding#request-and-receive-data) explains, the *VRFV2Wrapper* acts as a wrapper for the coordinator contract. 1. Open *VRFV2Wrapper.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *VRFV2Wrapper*. ![Image](/images/vrf/mock/v2-deploywrapper.jpg) 3. Under *DEPLOY*, fill in `_LINK` with the *LinkToken* contract address, `_LINKETHFEED` with the *MockV3Aggregator* contract address, and `_COORDINATOR` with the *VRFCoordinatorV2Mock* contract address. 4. click on *transact* to deploy the *VRFV2Wrapper* contract. 5. A Metamask popup will open. Click on *Confirm*. 6. Once deployed, you should see the *VRFV2Wrapper* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedwrapper.jpg) 7. Note the address of the deployed contract. ### Configure the VRFV2Wrapper 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFV2Wrapper* contract. 2. Click on `setConfig` and fill in `_wrapperGasOverhead` with `60000`, `_coordinatorGasOverhead` with `52000`, `_wrapperPremiumPercentage` with `10`, `_keyHash` with `0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc`, and `_maxNumWords` with `10`. **Note** on these variables: 1. `_wrapperGasOverhead`: This variable reflects the gas overhead of the wrapper's fulfillRandomWords function. The cost for this gas is passed to the user. 2. `_coordinatorGasOverhead`: This variable reflects the gas overhead of the coordinator's `fulfillRandomWords` function. The cost for this gas is billed to the *VRFV2Wrapper* subscription and must, therefore, be included in the VRF v2 direct funding requests pricing. 3. `_wrapperPremiumPercentage`: This variable is the premium ratio in percentage. For example, a value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. 4. `_keyHash`: The gas lane key hash value is the maximum gas price you are willing to pay for a request in wei. 5. `_maxNumWords`: This variable is the maximum number of words requested in a VRF v2 direct funding request. ![Image](/images/vrf/mock/v2-wrappersetconfig.jpg) 3. click on *transact*. 4. A Metamask popup will open. Click on *Confirm*. ### Fund the VRFV2Wrapper subscription When deployed, the *VRFV2Wrapper* contract creates a new subscription and adds itself to the newly created subscription. If you started this guide from scratch, the subscription ID should be 1. 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract. 2. Click `fundSubscription` to fund the *VRFV2Wrapper* subscription. In this example, you can set the `_subid` to `1` (which is your newly created subscription ID) and the `_amount` to `10000000000000000000` (10 LINK). 3. A Metamask popup will open. Click on *Confirm*. ### Deploy the VRF consumer contract 1. In the file explorer, open *RandomNumberDirectFundingConsumerV2.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *RandomNumberDirectFundingConsumerV2*. ![Image](/images/vrf/mock/v2-deploydfconsumer.jpg) 3. Under *DEPLOY*, fill in `_LINKADDRESS_` with the *LinkToken* contract address, and `_WRAPPERADDRESS_` with the deployed *VRFV2Wrapper* address. 4. Click on *transact* to deploy the *RandomNumberDirectFundingConsumerV2* contract. 5. A Metamask popup will open. Click on *Confirm*. 6. Once deployed, you should see the *RandomNumberDirectFundingConsumerV2* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployeddfconsumer.jpg) 7. Note the address of the deployed contract. ### Fund your VRF consumer contract 1. Under *Deployed Contracts*, open the functions list of your deployed *LinkToken* contract. 2. Click on *transfer* and fill in the `_to` with your consumer contract address and `_value` with LINK tokens amount. For this example, you can set the `_value` to `10000000000000000000` (10 LINK). ![Image](/images/vrf/mock/v2-linktransfer.jpg) 3. Click on *transact*. 4. A Metamask popup will open. Click on *Confirm*. ### Request random words Request three random words. 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2* contract. 2. In `requestRandomWords`, fill in `_callbackGasLimit` with `300000`, `_requestConfirmations` with `3` and `_numWords` with `3`. ![Image](/images/vrf/mock/v2-requestrandomwordsdf.jpg) 3. Click on *transact*. 4. A Metamask popup will open. > **NOTE: Set your gas limit in MetaMask** > > Remix IDE doesn't set the right gas limit, so you must [edit the > gas limit in MetaMask](https://support.metamask.io/hc/en-us/articles/360022895972) within the **Advanced gas controls** settings. > > For this example to work, set the gas limit to *400,000* in MetaMask. > > First, [enable **Advanced gas controls** in your MetaMask settings](https://support.metamask.io/hc/en-us/articles/360022895972). > > Before confirming your transaction in MetaMask, navigate to the screen where you can edit the gas limit: Select **Site suggested** > **Advanced** > **Advanced gas controls** and select **Edit** next to the **Gas limit** amount. Update the **Gas limit** value to *400000* and select **Save**. Finally, confirm the transaction. 5. Click on *Confirm*. 6. In the RemixIDE console, read your transaction logs to find the VRF request ID. In this example, the request ID is *1*. ![Image](/images/vrf/mock/v2-requestrandomwordslogsdf.jpg) 7. Note your request ID. ### Fulfill the VRF request Because you are testing on a local blockchain environment, you must fulfill the VRF request yourself. 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract. 2. Click `fulfillRandomWords` and fill in `_requestId` with your VRF request ID and `_consumer` with the *VRFV2Wrapper* contract address. ![Image](/images/vrf/mock/v2-fulfillrandomwordsdf.jpg) 3. Click on `transact`. 4. A Metamask popup will open. > **NOTE: Set your gas limit in MetaMask** > > Remix IDE doesn't set the right gas limit, so you must [edit the > gas limit in MetaMask](https://support.metamask.io/hc/en-us/articles/360022895972) within the **Advanced gas controls** settings. > > For this example to work, set the gas limit to *1,000,000* in MetaMask. > > First, [enable **Advanced gas controls** in your MetaMask settings](https://support.metamask.io/hc/en-us/articles/360022895972). > > Before confirming your transaction in MetaMask, navigate to the screen where you can edit the gas limit: Select **Site suggested** > **Advanced** > **Advanced gas controls** and select **Edit** next to the **Gas limit** amount. Update the **Gas limit** value to *1000000* and select **Save**. Finally, confirm the transaction. 5. Click on *Confirm*. 6. In the RemixIDE console, read your transaction logs to find the random words. ![Image](/images/vrf/mock/v2-requestfulfilledlogsdf.jpg) ### Check the results 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberDirectFundingConsumerV2* contract. 2. Click on `lastRequestId` to display the last request ID. In this example, the output is *1*. ![Image](/images/vrf/mock/v2-deployedconsumerrequestiddf.jpg) 3. Click on `getRequestStatus` with `_requestId` equal to `1`: ![Image](/images/vrf/mock/v2-deployedconsumerrequeststatusdf.jpg) 4. You will get the amount paid, the status, and the random words. ![Image](/images/vrf/mock/v2-deployedconsumerrequeststatusresultsdf.jpg) ## Next steps This guide demonstrated how to test a VRF v2 consumer contract on your local blockchain. We made the guide on RemixIDE for learning purposes, but you can reuse the same [testing logic](#testing-logic) on another development environment, such as Truffle or Hardhat. For example, read the Hardhat Starter Kit [RandomNumberDirectFundingConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberDirectFundingConsumer.spec.js). --- # Supported Networks - Direct Funding Method Source: https://docs.chain.link/vrf/v2/direct-funding/supported-networks Chainlink VRF allows you to integrate provably fair and verifiably random data in your smart contract. For implementation details, read [Introduction to Chainlink VRF v2 Direct funding method](/vrf/v2/direct-funding). ## Wrapper parameters These parameters are configured in the VRF v2 Wrapper contract. You can view these values by running `getConfig` on the VRF v2 Wrapper or by viewing the VRF v2 Wrapper contract in a blockchain explorer. - `uint32 stalenessSeconds`: How long the VRF v2 Wrapper waits until we consider the ETH/LINK price used for converting gas costs to LINK is stale and use `fallbackWeiPerUnitLink`. - `uint32 wrapperGasOverhead`: The gas overhead of the VRF v2 Wrapper's `fulfillRandomWords` function. - `uint32 coordinatorGasOverhead`: The gas overhead of the coordinator's `fulfillRandomWords` function. - `uint8 maxNumWords`: Maximum number of words that can be requested in a single wrapped VRF request. ## Coordinator parameters Some parameters are important to know and are configured in the coordinator contract. You can view these values by running `getConfig` on the coordinator or by viewing the coordinator contract in a blockchain explorer. - `uint16 minimumRequestConfirmations`: The minimum number of confirmation blocks on VRF requests before oracles respond - `uint32 maxGasLimit`: The maximum gas limit supported for a `fulfillRandomWords` callback. Note that you still need to subtract the `wrapperGasOverhead` for the accurate limit, as explained in [Direct funding limits](/vrf/v2/direct-funding/#limits). ## Fee parameters Fee parameters are configured in the VRF v2 Wrapper and the VRF v2 Coordinator contracts and specify the premium you pay per request in addition to the gas cost for the transaction. You can view them by running `getConfig` on the VRF v2 Wrapper: - The `uint32 fulfillmentFlatFeeLinkPPM` parameter is a flat fee and defines the fees per request specified in millionths of LINK. - The `uint8 wrapperPremiumPercentage` parameter defines the premium ratio in percentage. For example, a value of *0* indicates no premium. A value of *15* indicates a *15%* premium. The details for calculating the total transaction cost can be found [here](/vrf/v2/direct-funding/#request-and-receive-data). ## Configurations VRF v2 coordinators for direct funding are available on several networks. To see a list of coordinators for subscription funding, see the [Subscription Configurations](/vrf/v2/subscription/supported-networks) page. To use Chainlink VRF on certain networks, you may need to conduct token transfers. You can transfer tokens by using [Chainlink CCIP](/ccip/tutorials/evm/transfer-tokens-from-contract), [Transporter](https://www.transporter.io/) or third-party applications such as [XSwap](https://xswap.link/). > **NOTE: Interfaces and Applications** > > Chainlink CCIP is a messaging protocol. Third parties may build user interfaces or other applications on top of CCIP. > Neither Chainlink Labs nor the Chainlink Foundation owns, controls, endorses, or assumes any responsibility for any > such interfaces or applications. You are solely responsible for your use of such interfaces or applications. Please > visit the Chainlink Foundation [Terms of Service](https://chain.link/terms) for more information. > **CAUTION: Understand Risks associated with Bridges** > > If you are using a cross-chain bridge to transfer your LINK tokens, read the [Bridges and Associated Risks](/resources/bridge-risks) guide to understand what cross-chain bridges are and the risks associated with using them. ### Ethereum mainnet | Item | Value | | -------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x514910771AF9Ca656af840dff83E8264EcF986CA](https://etherscan.io/token/0x514910771AF9Ca656af840dff83E8264EcF986CA) | | VRF Wrapper | [0x5A861794B927983406fCE1D062e00b9368d97Df6](https://etherscan.io/address/0x5A861794B927983406fCE1D062e00b9368d97Df6) | | VRF Coordinator | [0x271682DEB8C4E0901D1a1550aD2e64D568E69909](https://etherscan.io/address/0x271682DEB8C4E0901D1a1550aD2e64D568E69909) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.25 LINK | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Sepolia testnet Testnet LINK and ETH are available from [faucets.chain.link](https://faucets.chain.link/sepolia). Testnet ETH is also available from several public [ETH faucets](https://faucetlink.to/sepolia). | Item | Value | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x779877A7B0D9E8603169DdbD7836e478b4624789](https://sepolia.etherscan.io/token/0x779877A7B0D9E8603169DdbD7836e478b4624789) | | | | | VRF Wrapper | [0xab18414CD93297B0d12ac29E63Ca20f515b3DB46](https://sepolia.etherscan.io/address/0xab18414CD93297B0d12ac29E63Ca20f515b3DB46) | | VRF Coordinator | [0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625](https://sepolia.etherscan.io/address/0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.25 LINK | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### BNB Chain mainnet > **TIP: Important** > > The LINK provided by the [BNB Chain Bridge](https://www.bnbchain.world/en/bridge) is not ERC-677 compatible, so cannot > be used with Chainlink oracles. However, it can be [**converted to the official LINK token on BNB Chain using > Chainlink's PegSwap service**](https://pegswap.chain.link/). | Item | Value | | -------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x404460C6A5EdE2D891e8297795264fDe62ADBB75](https://bscscan.com/token/0x404460C6A5EdE2D891e8297795264fDe62ADBB75) | | VRF Wrapper | [0x721DFbc5Cfe53d32ab00A9bdFa605d3b8E1f3f42](https://bscscan.com/address/0x721DFbc5Cfe53d32ab00A9bdFa605d3b8E1f3f42) | | VRF Coordinator | [0xc587d9053cd1118f25F645F9E08BB98c9712A4EE](https://bscscan.com/address/0xc587d9053cd1118f25F645F9E08BB98c9712A4EE) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.005 LINK | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### BNB Chain testnet Testnet LINK is available from [https://faucets.chain.link/bnb-chain-testnet](https://faucets.chain.link/bnb-chain-testnet) | Item | Value | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06](https://testnet.bscscan.com/address/0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06) | | VRF Wrapper | [0x699d428ee890d55D56d5FC6e26290f3247A762bd](https://testnet.bscscan.com/address/0x699d428ee890d55D56d5FC6e26290f3247A762bd) | | VRF Coordinator | [0x6A2AAd07396B36Fe02a22b33cf443582f682c82f](https://testnet.bscscan.com/address/0x6A2AAd07396B36Fe02a22b33cf443582f682c82f) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.005 LINK | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Polygon mainnet > **TIP: Important** > > The LINK provided by the [Polygon Bridge](https://wallet.polygon.technology/bridge) is not ERC-677 compatible, so > cannot be used with Chainlink oracles. However, it can be [**converted to the official LINK token on Polygon using > Chainlink's PegSwap service**](https://pegswap.chain.link/) | Item | Value | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | LINK Token | [0xb0897686c545045aFc77CF20eC7A532E3120E0F1](https://polygonscan.com/address/0xb0897686c545045aFc77CF20eC7A532E3120E0F1) | | VRF Wrapper | [0x4e42f0adEB69203ef7AaA4B7c414e5b1331c14dc](https://polygonscan.com/address/0x4e42f0adEB69203ef7AaA4B7c414e5b1331c14dc) | | VRF Coordinator | [0xAE975071Be8F8eE67addBC1A82488F1C24858067](https://polygonscan.com/address/0xAE975071Be8F8eE67addBC1A82488F1C24858067) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.0005 LINK | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Polygon Amoy testnet | Item | Value | | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904](https://amoy.polygonscan.com/address/0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904) | | VRF Coordinator | [0x7E10652Cb79Ba97bC1D0F38a1e8FaD8464a8a908](https://amoy.polygonscan.com/address/0x7E10652Cb79Ba97bC1D0F38a1e8FaD8464a8a908) | | 500 gwei Key Hash | 0x3f631d5ec60a0ce16203bcd6aff7ffbc423e22e452786288e172d467354304c8 | | Premium | 0.0005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Avalanche mainnet | Item | Value | | -------------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x5947BB275c521040051D82396192181b413227A3](https://snowtrace.io/address/0x5947BB275c521040051D82396192181b413227A3) | | VRF Wrapper | [0x721DFbc5Cfe53d32ab00A9bdFa605d3b8E1f3f42](https://snowtrace.io/address/0x721DFbc5Cfe53d32ab00A9bdFa605d3b8E1f3f42) | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://snowtrace.io/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Avalanche Fuji testnet Testnet LINK is available from [https://faucets.chain.link/fuji](https://faucets.chain.link/fuji) | Item | Value | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846](https://testnet.snowtrace.io/address/0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846) | | | | | VRF Wrapper | [0x9345AC54dA4D0B5Cda8CB749d8ef37e5F02BBb21](https://testnet.snowtrace.io/address/0x9345AC54dA4D0B5Cda8CB749d8ef37e5F02BBb21) | | VRF Coordinator | [0x2eD832Ba664535e5886b75D64C46EB9a228C2610](https://testnet.snowtrace.io/address/0x2eD832Ba664535e5886b75D64C46EB9a228C2610) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Fantom mainnet > **TIP: Important** > > You must use ERC-677 LINK on Fantom. ERC-20 LINK will not work with Chainlink services. Fantom is not supported in VRF > V2.5. | Item | Value | | -------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x6F43FF82CCA38001B6699a8AC47A2d0E66939407](https://ftmscan.com/token/0x6F43FF82CCA38001B6699a8AC47A2d0E66939407) | | | | | VRF Wrapper | [0xeDA5B00fB33B13c730D004Cf5D1aDa1ac191Ddc2](https://ftmscan.com/address/0xeDA5B00fB33B13c730D004Cf5D1aDa1ac191Ddc2) | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://ftmscan.com/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.0005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Fantom testnet > **NOTE: Fantom Testnet Faucet** > > Testnet LINK is available from [https://faucets.chain.link/fantom-testnet](https://faucets.chain.link/fantom-testnet). | Item | Value | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F](https://testnet.ftmscan.com/address/0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F) | | | | | VRF Wrapper | [0x38336BDaE79747a1d2c4e6C67BBF382244287ca6](https://testnet.ftmscan.com/address/0x38336BDaE79747a1d2c4e6C67BBF382244287ca6) | | VRF Coordinator | [0xbd13f08b8352A3635218ab9418E340c60d6Eb418](https://testnet.ftmscan.com/address/0xbd13f08b8352A3635218ab9418E340c60d6Eb418) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.0005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Arbitrum mainnet | Item | Value | | -------------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xf97f4df75117a78c1A5a0DBb814Af92458539FB4](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) | | | | | VRF Coordinator | [0x41034678D6C633D8a95c75e1138A360a28bA15d1](https://arbiscan.io/address/0x41034678D6C633D8a95c75e1138A360a28bA15d1) | | VRF Wrapper | [0x2D159AE3bFf04a10A355B608D22BDEC092e934fa](https://arbiscan.io/address/0x2D159AE3bFf04a10A355B608D22BDEC092e934fa) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.0005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | ### Arbitrum Sepolia testnet Testnet LINK is available from [https://faucets.chain.link/arbitrum-sepolia](https://faucets.chain.link/arbitrum-sepolia) | Item | Value | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xb1D4538B4571d411F07960EF2838Ce337FE1E80E](https://sepolia.arbiscan.io/address/0xb1D4538B4571d411F07960EF2838Ce337FE1E80E) | | | | | VRF Coordinator | [0x50d47e4142598E3411aA864e08a44284e471AC6f](https://sepolia.arbiscan.io/address/0x50d47e4142598E3411aA864e08a44284e471AC6f) | | VRF Wrapper | [0x1D3bb92db7659F2062438791F131CFA396dfb592](https://sepolia.arbiscan.io/address/0x1D3bb92db7659F2062438791F131CFA396dfb592) | | Wrapper Premium Percentage | 0 | | Coordinator Flat Fee | 0.0005 LINK | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 10 | | Wrapper Gas overhead | 40000 | | Coordinator Gas Overhead | 90000 | --- # VRF Billing Source: https://docs.chain.link/vrf/v2/estimating-costs This guide explains how to estimate VRF V2 costs for both the subscription and direct funding methods. > **TIP: VRF V2.5 billing information** > > VRF V2.5 adds the option to pay for VRF requests with native tokens as well as LINK. Learn more about [VRF V2.5 > billing](/vrf/v2-5/billing). ## VRF v2 cost calculator ## Understanding transaction costs ### Subscription For Chainlink VRF v2 to fulfill your requests, you must maintain a sufficient amount of LINK in your subscription balance. Gas cost calculation includes the following variables: - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. - **Verification gas:** The amount of gas used to verify randomness onchain. The gas price depends on current network conditions. The callback gas depends on your callback function, and the number of random values in your request. The cost of each request is final only after the transaction is complete, but you define the limits you are willing to spend for the request with the following variables: - **Gas lane:** The maximum gas price you are willing to pay for a request in wei. Define this limit by specifying the appropriate `keyHash` in your request. The limits of each gas lane are important for handling gas price spikes when Chainlink VRF bumps the gas price to fulfill your request quickly. - **Callback gas limit:** Specifies the maximum amount of gas you are willing to spend on the callback request. Define this limit by specifying the `callbackGasLimit` value in your request. ### Direct funding For Chainlink VRF v2 to fulfill your requests, you must have a sufficient amount of LINK in your consuming contract. Gas cost calculation includes the following variables: - **Gas price:** The current gas price, which fluctuates depending on network conditions. - **Callback gas:** The amount of gas used for the callback request that returns your requested random values. The callback gas depends on your callback function and the number of random values in your request. Set the **callback gas limit** to specify the maximum amount of gas you are willing to spend on the callback request. - **Verification gas:** The amount of gas used to verify randomness onchain. - **Wrapper overhead gas:** The amount of gas used by the VRF Wrapper contract. See the [Request and Receive Data](/vrf/v2/direct-funding#request-and-receive-data) section for details about the VRF v2 Wrapper contract design. Because the consuming contract directly pays the LINK for the request, the cost is calculated during the request and not during the callback when the randomness is fulfilled. Test your callback function to learn how to correctly estimate the callback gas limit. - If the gas limit is underestimated, the callback fails and the consuming contract is still charged for the work done to generate the requested random values. - If the gas limit is overestimated, the callback function will be executed but your contract is not refunded for the excess gas amount that you paid. Make sure that your consuming contracts are funded with enough LINK tokens to cover the transaction costs. If the consuming contract doesn't have enough LINK tokens, your request will revert. ### Estimate gas costs ### Subscription You need to pre-fund your subscription enough to meet the [minimum subscription balance](/vrf/v2/subscription#minimum-subscription-balance) in order to have a buffer against gas volatility. After the request is complete, the final gas cost is recorded based on how much gas is used for the verification and callback. The actual cost of the request is deducted from your subscription balance. The total gas cost in wei for your request uses the following formula: ``` (Gas price * (Verification gas + Callback gas)) = total gas cost ``` The total gas cost is converted to LINK using the ETH/LINK data feed. In the unlikely event that the data feed is unavailable, the VRF coordinator uses the `fallbackWeiPerUnitLink` value for the conversion instead. The `fallbackWeiPerUnitLink` value is defined in the [coordinator contract](/vrf/v2/subscription/supported-networks/#configurations) for your selected network. ### Direct funding The final gas cost to fulfill randomness is estimated based on how much gas is expected for the verification and callback. The total gas cost in wei uses the following formula: ``` (Gas price * (Verification gas + Callback gas limit + Wrapper gas overhead)) = total gas cost ``` The total gas cost is converted to LINK using the ETH/LINK data feed. In the unlikely event that the data feed is unavailable, the VRF Wrapper uses the `fallbackWeiPerUnitLink` value for the conversion instead. The `fallbackWeiPerUnitLink` value is defined in the [VRF v2 Wrapper contract](/vrf/v2/direct-funding/supported-networks/#configurations) for your selected network. The maximum allowed `callbackGasLimit` value for your requests is defined in the [Coordinator contract supported networks](/vrf/v2/subscription/supported-networks) page. Because the VRF v2 Wrapper adds a gas overhead, your `callbackGasLimit` must not exceed `maxGasLimit - wrapperGasOverhead`. ### Add LINK premium ### Subscription The LINK premium is added to the total gas cost. The premium is defined in the [coordinator contract](/vrf/v2/subscription/supported-networks/#configurations) with the `fulfillmentFlatFeeLinkPPMTier1` parameter in millionths of LINK. ``` (total gas cost + LINK premium) = total request cost ``` The total request cost is charged to your subscription balance. ### Direct funding A LINK premium is then added to the total gas cost. The premium is divided in two parts: - Wrapper premium: The premium percentage. You can find the percentage for your network in the [Supported networks](/vrf/v2/direct-funding/supported-networks/#configurations) page. - Coordinator premium: A flat fee. This premium is defined in the `fulfillmentFlatFeeLinkPPMTier1` parameter in millionths of LINK. You can find the flat fee of the coordinator for your network in the [Supported networks](/vrf/v2/direct-funding/supported-networks/#configurations) page. ``` (Coordinator premium + (total gas cost * (1 + Wrapper premium percentage)) = total request cost ``` ### Ethereum example ### Subscription This is an example calculation of a VRF request on the Ethereum network. The values for other supported networks are available on the [Supported Networks](/vrf/v2/subscription/supported-networks) page. #### Estimate minimum subscription balance You need to have the [minimum subscription balance](/vrf/v2/subscription#minimum-subscription-balance) for your requests to be processed. This provides a buffer in case gas prices go higher when processing the request. The actual cost of the request is usually lower than the minimum subscription balance. | Parameter | Value | | -------------------- | --------- | | Gas lane | 500 gwei | | Callback gas limit | 100000 | | Max verification gas | 200000 | | LINK premium | 0.25 LINK | 1. Calculate the total gas cost, using the maximum possible gas price for the selected gas lane, the estimated maximum verification gas, and the full callback gas limit: | Gas cost calculation | Total gas cost | | --------------------------------------------- | ------------------------- | | Gas price x (Verification gas + Callback gas) | | | 500 gwei x (200000 + 100000) | 150000000 gwei (0.15 ETH) | 2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.004 ETH per 1 LINK. | ETH to LINK cost conversion | Total gas cost (LINK) | | --------------------------- | --------------------- | | 0.15 ETH / 0.004 ETH/LINK | 37.5 LINK | 3. Add the LINK premium to get the total maximum cost of a request: | Adding LINK premium | Maximum request cost (LINK) | | ------------------------------------ | --------------------------- | | Total gas cost (LINK) + LINK premium | | | 37.5 LINK + 0.25 LINK | 37.75 LINK | This example request requires a minimum subscription balance of 37.75 LINK. Check the **Max Cost** in the Subscription Manager to view the minimum subscription balance for all your contracts. When your request is processed, the actual cost of the request is deducted from your subscription balance. #### Estimate VRF request cost This example reflects an estimate of how much a VRF request costs. Check [Etherscan](https://etherscan.io/gastracker) for current gas prices. | Parameter | Value | | --------------------- | --------- | | Actual gas price | 50 gwei | | Callback gas used | 95000 | | Verification gas used | 115000 | | LINK premium | 0.25 LINK | 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | --------------------------------------------- | -------------------------- | | Gas price x (Verification gas + Callback gas) | | | 50 gwei x (115000 + 95000) | 10500000 gwei (0.0105 ETH) | 2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.004 ETH per 1 LINK. | ETH to LINK cost conversion | Total gas cost (LINK) | | --------------------------- | --------------------- | | 0.0105 ETH / 0.004 ETH/LINK | 2.625 LINK | 3. Add the LINK premium to get the total cost of a request: | Adding LINK premium | Total request cost (LINK) | | ------------------------------------ | ------------------------- | | Total gas cost (LINK) + LINK premium | | | 2.625 LINK + 0.25 LINK | 2.875 LINK | This example request would cost 2.875 LINK, which is deducted from your subscription balance. ### Direct funding This is an example calculation of a VRF request on the Ethereum network. The values for other supported networks are available on the [Supported Networks](/vrf/v2/direct-funding/supported-networks) page. | Parameter | Value | | ------------------------------------------- | --------- | | Gas price | 50 gwei | | Callback gas limit | 100000 | | Coordinator gas overhead (Verification gas) | 90000 | | Wrapper gas overhead | 40000 | | Coordinator premium | 0.25 LINK | | Wrapper premium percentage | 0 | #### Steps 1. Calculate the total gas cost: | Gas cost calculation | Total gas cost | | -------------------------------------------------------------------------- | -------------------------- | | Gas price x (Verification gas + Callback gas limit + Wrapper gas overhead) | | | 50 gwei x (90000 + 100000 + 40000) | 11500000 gwei (0.0115 ETH) | 2. Convert the gas cost to LINK using the [LINK/ETH feed](https://data.chain.link/ethereum/mainnet/crypto-eth/link-eth). For this example, assume the feed returns a conversion value of Ξ0.004 ETH per 1 LINK. | ETH to LINK cost conversion | Total gas cost (LINK) | | --------------------------- | --------------------- | | 0.0115 ETH / 0.004 ETH/LINK | 2.875 LINK | 3. Add the LINK premium to get the total cost of a request: | Adding LINK premium | Total request cost (LINK) | | ------------------------------------------------------------------------- | ------------------------- | | Coordinator premium + (Total gas cost x (1 + Wrapper premium percentage)) | | | 0.25 LINK + (2.875 x (1 + 0)) | 3.125 LINK | This example request would cost 3.125 LINK. ### Arbitrum The total transaction costs for using Arbitrum involve both L2 gas costs and L1 costs. Arbitrum transactions are [posted in batches to L1 Ethereum](https://developer.arbitrum.io/inside-arbitrum-nitro/#how-the-sequencer-publishes-the-sequence), which incurs an L1 cost. For an individual transaction, the total cost includes part of the L1 cost incurred to post the batch that included the transaction. To learn how to estimate gas costs for Arbitrum, refer to the [Arbitrum gas estimation tutorial](https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas) and the full [Arbitrum gas estimation script](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/gas-estimation) using their SDK. There is also a [**version of Arbitrum's gas estimation script extended to include VRF calculations**](#arbitrum-and-vrf-gas-estimation-code). #### Estimating Arbitrum gas costs with VRF ### Subscription VRF gas costs are calculated based on the amount of verification gas and callback gas used, multiplied by the gas price: ``` (Gas price * (Verification gas + Callback gas)) = total gas cost ``` For VRF Arbitrum transactions, add a buffer to estimate the additional L1 cost: ``` (L2GasPrice * (Verification gas + Callback gas + L1 calldata gas buffer))) = total estimated gas cost ``` To calculate the L1 callback gas buffer: - `calldataSizeBytes`: A static size for the transaction's calldata in bytes. Total: 720 bytes. - The amount Arbitrum adds to account for the static part of the transaction, fixed at 140 bytes. - The size of an ABI-encoded VRF V2 fulfillment, fixed at 580 bytes (`fulfillmentTxSizeBytes`). - `L1PricePerByte`: The estimated cost of posting 1 byte of data on L1, which varies with L1 network gas prices. - `L2GasPrice`: The L2 gas price, which varies with L2 network gas prices. ``` L1 calldata gas buffer = (calldataSizeBytes * L1PricePerByte) / L2GasPrice = (720 * L1PricePerByte) / L2GasPrice ``` This conversion allows us to estimate the L1 callback gas cost and incorporate it into the overall L2 gas estimate. You can add this estimated L1 callback gas buffer directly to the verification and callback gas: ``` (L2GasPrice * (Verification gas + Callback gas + ((calldataSizeBytes * L1PricePerByte) / L2GasPrice)))) = total estimated gas cost ``` ### Direct funding VRF gas costs are calculated based on the amount of verification gas, callback gas and wrapper gas overhead, multiplied by the gas price: ``` (Gas price * (Verification gas + Callback gas + Wrapper gas overhead)) = total gas cost ``` For VRF Arbitrum transactions, add a buffer to estimate the additional L1 cost: ``` (L2GasPrice * (Verification gas + Callback gas + Wrapper gas overhead + L1 calldata gas buffer))) = total estimated gas cost ``` To calculate the L1 callback gas buffer: - `calldataSizeBytes`: A static size for the transaction's calldata in bytes. Total: 720 bytes. - The amount Arbitrum adds to account for the static part of the transaction, fixed at 140 bytes. - The size of an ABI-encoded VRF V2 fulfillment, fixed at 580 bytes (`fulfillmentTxSizeBytes`). - `L1PricePerByte`: The estimated cost of posting 1 byte of data on L1, which varies with L1 network gas prices. - `L2GasPrice`: The L2 gas price, which varies with L2 network gas prices. ``` L1 calldata gas buffer = (calldataSizeBytes * L1PricePerByte) / L2GasPrice = (720 * L1PricePerByte) / L2GasPrice ``` This conversion allows us to estimate the L1 callback gas cost and incorporate it into the overall L2 gas estimate. You can add this estimated L1 callback gas buffer directly to the verification, callback, and wrapper gas: ``` (L2GasPrice * (Verification gas + Callback gas + Wrapper gas overhead + ((calldataSizeBytes * L1PricePerByte) / L2GasPrice)))) = total estimated gas cost ``` #### Arbitrum and VRF gas estimation code This sample extends the [original Arbitrum gas estimation script](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/gas-estimation) to estimate gas costs for VRF subscription and direct funding requests on Arbitrum. The following snippet shows only the VRF variables and calculations that were added to the Arbitrum gas estimation script. To learn more about how Arbitrum gas is calculated, refer to the [Arbitrum gas estimation tutorial](https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas). To run this code, use the [**full Arbitrum gas estimation script that includes VRF calculations**](https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf-arbitrum-gas-estimation). ```typescript // VRF variables and calculations // --------------------------------- // Full script: https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf-arbitrum-gas-estimation // --------------------------------- // Estimated upper bound of verification gas for VRF subscription. // To see an estimate with an average amount of verification gas, // adjust this to 115000. const maxVerificationGas = 200000 // The L1 Calldata size includes: // Arbitrum's static 140 bytes for transaction metadata // VRF V2's static 580 bytes, the size of a fulfillment's calldata abi-encoded in bytes // (from s_fulfillmentTxSizeBytes in VRFV2Wrapper.sol) const VRFCallDataSizeBytes = 140 + 580 // For direct funding only. Coordinator gas is verification gas const wrapperGasOverhead = 40000 const coordinatorGasOverhead = 90000 // VRF user settings const callbackGasLimit = 175000 // Estimate VRF L1 buffer const VRFL1CostEstimate = L1P.mul(VRFCallDataSizeBytes) const VRFL1Buffer = VRFL1CostEstimate.div(P) // VRF Subscription gas estimate // L2 gas price (P) * (maxVerificationGas + callbackGasLimit + VRFL1Buffer) const VRFL2SubscriptionGasSubtotal = BigNumber.from(maxVerificationGas + callbackGasLimit) const VRFSubscriptionGasTotal = VRFL2SubscriptionGasSubtotal.add(VRFL1Buffer) const VRFSubscriptionGasEstimate = P.mul(VRFSubscriptionGasTotal) // VRF Direct funding gas estimate // L2 gas price (P) * (coordinatorGasOverhead + callbackGasLimit + wrapperGasOverhead + VRFL1Buffer) const VRFL2DirectFundingGasSubtotal = BigNumber.from(coordinatorGasOverhead + wrapperGasOverhead + callbackGasLimit) const VRFDirectFundingGasTotal = VRFL2DirectFundingGasSubtotal.add(VRFL1Buffer) const VRFDirectFundingGasEstimate = P.mul(VRFDirectFundingGasTotal) ``` --- # Getting Started with Chainlink VRF Source: https://docs.chain.link/vrf/v2/getting-started > **NOTE: Newer version of VRF available** > > Try the [Getting Started with Chainlink VRF V2.5](/vrf/v2-5/getting-started) tutorial. VRF v2 - Developer Walkthrough In this guide, you will learn about generating randomness on blockchains. This includes learning how to implement a Request and Receive cycle with Chainlink oracles and how to consume random numbers with Chainlink VRF in smart contracts. ## How is randomness generated on blockchains? What is Chainlink VRF? Randomness is very difficult to generate on blockchains. This is because every node on the blockchain must come to the same conclusion and form a consensus. Even though random numbers are versatile and useful in a variety of blockchain applications, they cannot be generated natively in smart contracts. The solution to this issue is [**Chainlink VRF**](/vrf), also known as Chainlink Verifiable Random Function. ## What is the Request and Receive cycle? The [Data Feeds Getting Started](/data-feeds/getting-started) guide explains how to consume Chainlink Data Feeds, which consist of reference data posted onchain by oracles. This data is stored in a contract and can be referenced by consumers until the oracle updates the data again. Randomness, on the other hand, cannot be reference data. If the result of randomness is stored onchain, any actor could retrieve the value and predict the outcome. Instead, randomness must be requested from an oracle, which generates a number and a cryptographic proof. Then, the oracle returns that result to the contract that requested it. This sequence is known as the **[Request and Receive cycle](/architecture-overview/architecture-request-model)**. ## What is the payment process for generating a random number? VRF requests receive funding from subscription accounts. The [Subscription Manager](https://vrf.chain.link) lets you create an account and pre-pay for VRF requests, so that funding of all your application requests are managed in a single location. To learn more about VRF requests funding, see [Subscriptions limits](/vrf/v2/subscription#subscription-limits). ## How can I use Chainlink VRF? To see a basic implementation of Chainlink VRF, see [Get a Random Number](/vrf/v2/subscription/examples/get-a-random-number). In this section, you will create an application that uses Chainlink VRF to generate randomness. The contract used in this application has a [*Game of Thrones*](https://en.wikipedia.org/wiki/Game_of_Thrones) theme. After the contract requests randomness from Chainlink VRF, the result of the randomness will transform into a number between 1 and 20, mimicking the rolling of a 20 sided die. Each number represents a *Game of Thrones* house. If the dice land on the value 1, the user is assigned house Targaryan, 2 for Lannister, and so on. A full list of houses can be found [here](https://gameofthrones.fandom.com/wiki/Great_House). When rolling the dice, it uses an `address` variable to track which address is assigned to each house. The contract has the following functions: - `rollDice`: This submits a randomness request to Chainlink VRF - `fulfillRandomWords`: The function that the Oracle uses to send the result back - `house`: To see the assigned house of an address **Note**: to jump straight to the entire implementation, you can [open the VRFD20.sol contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFD20.sol) in remix. ### Create and fund a subscription Chainlink VRF requests receive funding from subscription accounts. The [Subscription Manager](https://vrf.chain.link) lets you create an account and pre-pay your use of Chainlink VRF requests. For this example, create a new subscription on the Sepolia testnet as explained [here](/vrf/v2/subscription/examples/get-a-random-number/#create-and-fund-a-subscription). ### Importing `VRFConsumerBaseV2` and `VRFCoordinatorV2Interface` Chainlink maintains a [library of contracts](https://github.com/smartcontractkit/chainlink/tree/contracts-v1.3.0/contracts) that make consuming data from oracles easier. For Chainlink VRF, you will use: - [`VRFConsumerBaseV2`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol) that must be imported and extended from the contract that you create. - [`VRFCoordinatorV2Interface`](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol) that must be imported to communicate with the VRF coordinator. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; contract VRFD20 is VRFConsumerBaseV2 { } ``` ### Contract variables This example is adapted for [Sepolia testnet](/vrf/v2/subscription/supported-networks/#sepolia-testnet) but you can change the configuration and make it run for any [supported network](/vrf/v2/subscription/supported-networks/#configurations). ```solidity uint64 s_subscriptionId; address s_owner; VRFCoordinatorV2Interface COORDINATOR; address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625; bytes32 s_keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; uint32 callbackGasLimit = 40000; uint16 requestConfirmations = 3; uint32 numWords = 1; ``` - `uint64 s_subscriptionId`: The subscription ID that this contract uses for funding requests. Initialized in the `constructor`. - `address s_owner`: The address of the owner of the contract that you will deploy. This is initialized in the `constructor`, and it will be the address you use when deploying the contract. - `VRFCoordinatorV2Interface COORDINATOR`: The address of the Chainlink VRF Coordinator contract that this contract will use. Initialized in the `constructor`. - `address vrfCoordinator`: The address of the Chainlink VRF Coordinator contract. - `bytes32 s_keyHash`: The gas lane key hash value, which is the maximum gas price you are willing to pay for a request in wei. It functions as an ID of the offchain VRF job that runs in response to requests. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords` function. It must be less than the `maxGasLimit` on the coordinator contract. Adjust this value for larger requests depending on how your `fulfillRandomWords` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your subscription is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` limit on the coordinator contract. - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. In this example, each transaction requests one random value. To keep track of addresses that roll the dice, the contract uses mappings. [Mappings](https://medium.com/upstate-interactive/mappings-in-solidity-explained-in-under-two-minutes-ecba88aff96e) are unique key-value pair data structures similar to hash tables in Java. ```solidity mapping(uint256 => address) private s_rollers; mapping(address => uint256) private s_results; ``` - `s_rollers` stores a mapping between the `requestID` (returned when a request is made), and the address of the roller. This is so the contract can keep track of who to assign the result to when it comes back. - `s_results` stores the roller and the result of the dice roll. ### Initializing the contract The coordinator and subscription id must be initialized in the `constructor` of the contract. To use `VRFConsumerBaseV2` properly, you must also pass the VRF coordinator address into its constructor. The address that creates the smart contract is the owner of the contract. the modifier `onlyOwner()` checks that only the owner is allowed to do some tasks. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; contract VRFD20 is VRFConsumerBaseV2 { // variables // ... // constructor constructor(uint64 subscriptionId) VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_owner = msg.sender; s_subscriptionId = subscriptionId; } //... modifier onlyOwner() { require(msg.sender == s_owner); _; } } ``` ### `rollDice` function The `rollDice` function will complete the following tasks: 1. Check if the roller has already rolled since each roller can only ever be assigned to a single house. 2. Request randomness by calling the VRF coordinator. 3. Store the `requestId` and roller address. 4. Emit an event to signal that the dice is rolling. You must add a `ROLL_IN_PROGRESS` constant to signify that the dice has been rolled but the result is not yet returned. Also add a `DiceRolled` event to the contract. Only the owner of the contract can execute the `rollDice` function. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; contract VRFD20 is VRFConsumerBaseV2 { // variables uint256 private constant ROLL_IN_PROGRESS = 42; // ... // events event DiceRolled(uint256 indexed requestId, address indexed roller); // ... // ... // { constructor } // ... // rollDice function function rollDice(address roller) public onlyOwner returns (uint256 requestId) { require(s_results[roller] == 0, "Already rolled"); // Will revert if subscription is not set and funded. requestId = COORDINATOR.requestRandomWords( s_keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); s_rollers[requestId] = roller; s_results[roller] = ROLL_IN_PROGRESS; emit DiceRolled(requestId, roller); } } ``` ### `fulfillRandomWords` function `fulfillRandomWords` is a special function defined within the `VRFConsumerBaseV2` contract that our contract extends from. The coordinator sends the result of our generated `randomWords` back to `fulfillRandomWords`. You will implement some functionality here to deal with the result: 1. Change the result to a number between 1 and 20 inclusively. Note that `randomWords` is an array that could contain several random values. In this example, request 1 random value. 2. Assign the transformed value to the address in the `s_results` mapping variable. 3. Emit a `DiceLanded` event. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; contract VRFD20 is VRFConsumerBaseV2 { // ... // { variables } // ... // events // ... event DiceLanded(uint256 indexed requestId, uint256 indexed result); // ... // { constructor } // ... // ... // { rollDice function } // ... // fulfillRandomWords function function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { // transform the result to a number between 1 and 20 inclusively uint256 d20Value = (randomWords[0] % 20) + 1; // assign the transformed value to the address in the s_results mapping variable s_results[s_rollers[requestId]] = d20Value; // emitting event to signal that dice landed emit DiceLanded(requestId, d20Value); } } ``` ### `house` function Finally, the `house` function returns the house of an address. To have a list of the house's names, create the `getHouseName` function that is called in the `house` function. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; contract VRFD20 is VRFConsumerBaseV2 { // ... // { variables } // ... // ... // { events } // ... // ... // { constructor } // ... // ... // { rollDice function } // ... // ... // { fulfillRandomWords function } // ... // house function function house(address player) public view returns (string memory) { // dice has not yet been rolled to this address require(s_results[player] != 0, "Dice not rolled"); // not waiting for the result of a thrown dice require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress"); // returns the house name from the name list function return getHouseName(s_results[player]); } // getHouseName function function getHouseName(uint256 id) private pure returns (string memory) { // array storing the list of house's names string[20] memory houseNames = [ "Targaryen", "Lannister", "Stark", "Tyrell", "Baratheon", "Martell", "Tully", "Bolton", "Greyjoy", "Arryn", "Frey", "Mormont", "Tarley", "Dayne", "Umber", "Valeryon", "Manderly", "Clegane", "Glover", "Karstark" ]; // returns the house name given an index return houseNames[id - 1]; } } ``` [Open VRFD20.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFD20.sol) You have now completed all necessary functions to generate randomness and assign the user a *Game of Thrones* house. We've added a few helper functions in there to make using the contract easier and more flexible. You can deploy and interact with the complete contract in Remix. ## How do I deploy to testnet? You will deploy this contract on the Sepolia test network. You must have some Sepolia testnet ETH in your MetaMask account to pay for the gas. Testnet ETH is also available from several [public faucets](https://faucetlink.to/sepolia). This deployment is slightly different than the example in the [Deploy Your First Contract](/quickstarts/deploy-your-first-contract) guide. In this case, you pass in parameters to the constructor upon deployment. Once compiled, you'll see a dropdown menu that looks like this in the deploy pane: ![Remix contract selected](/files/intermediates-tutorial-01.png) Select the `VRFD20` contract or the name that you gave to your contract. Click the caret arrow on the right hand side of **Deploy** to expand the parameter fields, and paste your subscription ID. ![Remix contract parameters to deploy](/files/intermediates-tutorial-02.png) Then click the `Deploy` button and use your MetaMask account to confirm the transaction. > **NOTE: Address, Key Hashes and more** > > For a full reference of the addresses, key hashes and fees for each network, see [VRF Supported > Networks](/vrf/v2/subscription/supported-networks/#configurations). At this point, your contract should be successfully deployed. However, it can't request anything because it is not yet approved to use the LINK balance in your subscription. If you click `rollDice`, the transaction will revert. ## How do I add my contract to my subscription account? After you deploy your contract, you must add it as an approved consumer contract so it can use the subscription balance when requesting for randomness. Go to the [Subscription Manager](https://vrf.chain.link) and add your deployed contract address to the list of consumers. Find your contract address in Remix under **Deployed Contracts** on the bottom left. ![Remix contract address](/files/intermediates-tutorial-03.png) ## How do I test `rollDice`? After you open the deployed contract tab in the bottom left, the function buttons are available. Find `rollDice` and click the caret to expand the parameter fields. Enter an Ethereum address to specify a "dice roller", and click 'rollDice'. It takes a few minutes for the transaction to confirm and the response to be sent back. You can get your house by clicking the `house` function button with the address passed in `rollDice`. After the response is sent back, you'll be assigned a *Game of Thrones* house! ## Further Reading To read more about generating random numbers in Solidity, read our blog posts: - [35+ Blockchain RNG Use Cases Enabled by Chainlink VRF](https://blog.chain.link/blockchain-rng-use-cases-enabled-by-chainlink-vrf/) - [How to Build Dynamic NFTs on Polygon](https://blog.chain.link/how-to-build-dynamic-nfts-on-polygon/) - [Chainlink VRF v2 Now Live on Ethereum Mainnet](https://blog.chain.link/vrf-v2-mainnet-launch/) --- # VRF Security Considerations Source: https://docs.chain.link/vrf/v2/security Gaining access to high quality randomness onchain requires a solution like Chainlink's VRF, but it also requires you to understand some of the ways that miners or validators can potentially manipulate randomness generation. Here are some of the top security considerations you should review in your project. - [Use `requestId` to match randomness requests with their fulfillment in order](#use-requestid-to-match-randomness-requests-with-their-fulfillment-in-order) - [Choose a safe block confirmation time, which will vary between blockchains](#choose-a-safe-block-confirmation-time-which-will-vary-between-blockchains) - [Do not allow re-requesting or cancellation of randomness](#do-not-allow-re-requesting-or-cancellation-of-randomness) - [Don't accept bids/bets/inputs after you have made a randomness request](#dont-accept-bidsbetsinputs-after-you-have-made-a-randomness-request) - [The `fulfillRandomWords` function must not revert](#fulfillrandomwords-must-not-revert) - [Use `VRFConsumerBaseV2` in your contract to interact with the VRF service](#use-vrfconsumerbasev2-in-your-contract-to-interact-with-the-vrf-service) ## Use `requestId` to match randomness requests with their fulfillment in order If your contract could have multiple VRF requests in flight simultaneously, you must ensure that the order in which the VRF fulfillments arrive cannot be used to manipulate your contract's user-significant behavior. Blockchain miners/validators can control the order in which your requests appear onchain, and hence the order in which your contract responds to them. For example, if you made randomness requests `A`, `B`, `C` in short succession, there is no guarantee that the associated randomness fulfillments will also be in order `A`, `B`, `C`. The randomness fulfillments might just as well arrive at your contract in order `C`, `A`, `B` or any other order. We recommend using the `requestID` to match randomness requests with their corresponding fulfillments. ## Choose a safe block confirmation time, which will vary between blockchains In principle, miners/validators of your underlying blockchain could rewrite the chain's history to put a randomness request from your contract into a different block, which would result in a different VRF output. Note that this does not enable a miner to determine the random value in advance. It only enables them to get a fresh random value that might or might not be to their advantage. By way of analogy, they can only re-roll the dice, not predetermine or predict which side it will land on. You must choose an appropriate confirmation time for the randomness requests you make. Confirmation time is how many blocks the VRF service waits before writing a fulfillment to the chain to make potential rewrite attacks unprofitable in the context of your application and its value-at-risk. ## Do not allow re-requesting or cancellation of randomness Any re-request or cancellation of randomness is an incorrect use of VRFv2. dApps that implement the ability to cancel or re-request randomness for specific commitments must consider the additional attack vectors created by this capability. For example, you must prevent the ability for any party to discard unfavorable randomness. ## Don't accept bids/bets/inputs after you have made a randomness request Consider the example of a contract that mints a random NFT in response to a user's actions. The contract should: 1. Record whatever actions of the user may affect the generated NFT. 2. **Stop accepting further user actions that might affect the generated NFT** and issue a randomness request. 3. On randomness fulfillment, mint the NFT. Generally speaking, whenever an outcome in your contract depends on some user-supplied inputs and randomness, the contract should not accept any additional user-supplied inputs after it submits the randomness request. Otherwise, the cryptoeconomic security properties may be violated by an attacker that can rewrite the chain. ## `fulfillRandomWords` must not revert If your `fulfillRandomWords()` implementation reverts, the VRF service will not attempt to call it a second time. Make sure your contract logic does not revert. Consider simply storing the randomness and taking more complex follow-on actions in separate contract calls made by you, your users, or an [Automation Node](/chainlink-automation). ## Use `VRFConsumerBaseV2` in your contract, to interact with the VRF service If you implement the [subscription method](/vrf/v2/subscription), use `VRFConsumerBaseV2`. It includes a check to ensure the randomness is fulfilled by `VRFCoordinatorV2`. For this reason, it is a best practice to inherit from `VRFConsumerBaseV2`. Similarly, don't override `rawFulfillRandomness`. ## Use `VRFv2WrapperConsumer.sol` in your contract, to interact with the VRF service If you implement the [direct funding method](/vrf/v2/direct-funding), use `VRFv2WrapperConsumer`. It includes a check to ensure the randomness is fulfilled by the `VRFV2Wrapper`. For this reason, it is a best practice to inherit from `VRFv2WrapperConsumer`. Similarly, don't override `rawFulfillRandomWords`. --- # Get a Random Number with VRF V2 Source: https://docs.chain.link/vrf/v2/subscription/examples/get-a-random-number > **TIP: VRF V2.5 Subscription Tutorial** > > Refer to the [VRF V2.5 version of this tutorial](/vrf/v2-5/subscription/get-a-random-number) to learn how the > subscription method works in VRF V2.5. To compare V2.5 and V2, refer to the [migration > guide](/vrf/v2-5/migration-from-v2). This guide explains how to get random values using a simple contract to request and receive random values from Chainlink VRF v2. For more advanced examples with programmatic subscription configuration, see the [Programmatic Subscription](/vrf/v2/subscription/examples/programmatic-subscription) page. To explore more applications of VRF, refer to our [blog](https://blog.chain.link/). ## Requirements This guide assumes that you know how to create and deploy smart contracts on Ethereum testnets using the following tools: - [The Remix IDE](https://remix.ethereum.org/) - [MetaMask](https://metamask.io/) - [Sepolia testnet ETH](/resources/link-token-contracts/#sepolia-testnet) If you are new to developing smart contracts on Ethereum, see the [Getting Started](/getting-started/conceptual-overview) guide to learn the basics. ## Create and fund a subscription For this example, create a new subscription on the Sepolia testnet. 1. Open MetaMask and set it to use the Sepolia testnet. The [Subscription Manager](/vrf/v2/subscription/ui) detects your network based on the active network in MetaMask. 2. Check MetaMask to make sure you have testnet ETH and LINK on Sepolia. You can get testnet ETH and LINK at [faucets.chain.link](https://faucets.chain.link/sepolia/). 3. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link). [Open the Subscription Manager](https://vrf.chain.link) 4. Click **Create Subscription** and follow the instructions to create a new subscription account. If you connect your wallet to the Subscription Manager, the **Admin address** for your subscription is prefilled and not editable. Optionally, you can enter an email address and a project name for your subscription, and both of these are private. MetaMask opens and asks you to confirm payment to create the account onchain. After you approve the transaction, the network confirms the creation of your subscription account onchain. 5. After the subscription is created, click **Add funds** and follow the instructions to fund your subscription. - For your request to go through, you need to fund your subscription with enough LINK to meet your [minimum subscription balance](/vrf/v2/subscription#minimum-subscription-balance) to serve as a buffer against gas volatility. For this example, a balance of 12 LINK is sufficient. (After your request is processed, it costs around 3 LINK, and that amount will be deducted from your subscription balance.) - MetaMask opens to confirm the LINK transfer to your subscription. After you approve the transaction, the network confirms the transfer of your LINK token to your subscription account. 6. After you add funds, click **Add consumer**. A page opens with your account details and subscription ID. 7. Record your subscription ID, which you need for your consuming contract. You will add the consuming contract to your subscription later. You can always find your subscription IDs, balances, and consumers at [vrf.chain.link](https://vrf.chain.link/). Now that you have a funded subscription account and your subscription ID, [create and deploy a VRF v2 compatible contract](#create-and-deploy-a-vrf-v2-compatible-contract). ## Create and deploy a VRF v2 compatible contract For this example, use the [VRFv2Consumer.sol](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2Consumer.sol) sample contract. This contract imports the following dependencies: - `VRFConsumerBaseV2.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol) - `VRFCoordinatorV2Interface.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol) - `ConfirmedOwner.sol`[(link)](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/shared/access/ConfirmedOwner.sol) The contract also includes pre-configured values for the necessary request parameters such as `vrfCoordinator` address, gas lane `keyHash`, `callbackGasLimit`, `requestConfirmations` and number of random words `numWords`. You can change these parameters if you want to experiment on different testnets, but for this example you only need to specify `subscriptionId` when you deploy the contract. Build and deploy the contract on Sepolia. 1. Open the [`VRFv2Consumer.sol` contract](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2Consumer.sol) in Remix. [Open VRFv2Consumer.sol in Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2Consumer.sol) 2. On the **Compile** tab in Remix, compile the `VRFv2Consumer.sol` contract. 3. Configure your deployment. On the **Deploy** tab in Remix, select the **Injected Provider** environment, select the `VRFv2Consumer` contract from the contract list, and specify your `subscriptionId` so the constructor can set it. ![Example showing the deploy button with the subscriptionID field filled in Remix](/images/vrf/deployWithSubscriptionId.png) 4. Click the **Deploy** button to deploy your contract onchain. MetaMask opens and asks you to confirm the transaction. 5. After you deploy your contract, copy the address from the **Deployed Contracts** list in Remix. Before you can request randomness from VRF v2, you must add this address as an approved consuming contract on your subscription account. ![Example showing the contract address listed under the Contracts list in Remix](/images/vrf/getContractAddress.png) 6. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link/) and click the ID of your new subscription under the **My Subscriptions** list. The subscription details page opens. 7. Under the **Consumers** section, click **Add consumer**. 8. Enter the address of your consuming contract that you just deployed and click **Add consumer**. MetaMask opens and asks you to confirm the transaction. Your example contract is deployed and approved to use your subscription balance to pay for VRF v2 requests. Next, [request random values](#request-random-values) from Chainlink VRF. ## Request random values The deployed contract requests random values from Chainlink VRF, receives those values, builds a struct `RequestStatus` containing them and stores the struct in a mapping `s_requests`. Run the `requestRandomWords()` function on your contract to start the request. 1. Return to Remix and view your deployed contract functions in the **Deployed Contracts** list. 2. Click the `requestRandomWords()` function to send the request for random values to Chainlink VRF. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF processes your request. Chainlink VRF fulfills the request and returns the random values to your contract in a callback to the `fulfillRandomWords()` function. At this point, a new key `requestId` is added to the mapping `s_requests`. Depending on current testnet conditions, it might take a few minutes for the callback to return the requested random values to your contract. You can see a list of pending requests for your subscription ID at [vrf.chain.link](https://vrf.chain.link/). 3. To fetch the request ID of your request, call `lastRequestId()`. 4. After the oracle returns the random values to your contract, the mapping `s_requests` is updated: The received random values are stored in `s_requests[_requestId].randomWords`. 5. Call `getRequestStatus()` specifying the `requestId` to display the random words. You deployed a simple contract that can request and receive random values from Chainlink VRF. To see more advanced examples where the contract can complete the entire process including subscription setup and management, see the [Programmatic Subscription](/vrf/v2/subscription/examples/programmatic-subscription) page. > **NOTE: Note on Requesting Randomness** > > Do not allow re-requesting or cancellation of randomness. For more information, see the [VRF Security > Considerations](/vrf/v2/security#do-not-allow-re-requesting-or-cancellation-of-randomness) page. ## Analyzing the contract In this example, your MetaMask wallet is the subscription owner and you created a consuming contract to use that subscription. The consuming contract uses static configuration parameters. ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.7; import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner { event RequestSent(uint256 requestId, uint32 numWords); event RequestFulfilled(uint256 requestId, uint256[] randomWords); struct RequestStatus { bool fulfilled; // whether the request has been successfully fulfilled bool exists; // whether a requestId exists uint256[] randomWords; } mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ VRFCoordinatorV2Interface COORDINATOR; // Your subscription ID. uint64 s_subscriptionId; // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf/v2/subscription/supported-networks/#configurations bytes32 keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 numWords = 2; /** * HARDCODED FOR SEPOLIA * COORDINATOR: 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625 */ constructor( uint64 subscriptionId ) VRFConsumerBaseV2(0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625) ConfirmedOwner(msg.sender) { COORDINATOR = VRFCoordinatorV2Interface(0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625); s_subscriptionId = subscriptionId; } // Assumes the subscription is funded sufficiently. function requestRandomWords() external onlyOwner returns (uint256 requestId) { // Will revert if subscription is not set and funded. requestId = COORDINATOR.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords); s_requests[requestId] = RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false}); requestIds.push(requestId); lastRequestId = requestId; emit RequestSent(requestId, numWords); return requestId; } function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { require(s_requests[_requestId].exists, "request not found"); s_requests[_requestId].fulfilled = true; s_requests[_requestId].randomWords = _randomWords; emit RequestFulfilled(_requestId, _randomWords); } function getRequestStatus( uint256 _requestId ) external view returns (bool fulfilled, uint256[] memory randomWords) { require(s_requests[_requestId].exists, "request not found"); RequestStatus memory request = s_requests[_requestId]; return (request.fulfilled, request.randomWords); } } ``` The parameters define how your requests will be processed. You can find the values for your network in the [Configuration](/vrf/v2/subscription/supported-networks) page. - `uint64 s_subscriptionId`: The subscription ID that this contract uses for funding requests. - `bytes32 keyHash`: The gas lane key hash value, which is the maximum gas price you are willing to pay for a request in wei. It functions as an ID of the offchain VRF job that runs in response to requests. - `uint32 callbackGasLimit`: The limit for how much gas to use for the callback request to your contract's `fulfillRandomWords()` function. It must be less than the `maxGasLimit` limit on the coordinator contract. Adjust this value for larger requests depending on how your `fulfillRandomWords()` function processes and stores the received random values. If your `callbackGasLimit` is not sufficient, the callback will fail and your subscription is still charged for the work done to generate your requested random values. - `uint16 requestConfirmations`: How many confirmations the Chainlink node should wait before responding. The longer the node waits, the more secure the random value is. It must be greater than the `minimumRequestBlockConfirmations` limit on the coordinator contract. - `uint32 numWords`: How many random values to request. If you can use several random values in a single callback, you can reduce the amount of gas that you spend per random value. The total cost of the callback request depends on how your `fulfillRandomWords()` function processes and stores the received random values, so adjust your `callbackGasLimit` accordingly. The contract includes the following functions: - `requestRandomWords()`: Takes your specified parameters and submits the request to the VRF coordinator contract. - `fulfillRandomWords()`: Receives random values and stores them with your contract. - `getRequestStatus()`: Retrieve request details for a given `_requestId`. > **NOTE: Security Considerations** > > Be sure to review your contracts to make sure they follow the best practices on the [security > considerations](/vrf/v2/security) page. ## Clean up After you are done with this contract and the subscription, you can retrieve the remaining testnet LINK to use with other examples. 1. Open the Subscription Manager at [vrf.chain.link](https://vrf.chain.link/) and click the ID of your new subscription under the **My Subscriptions** list. The subscription details page opens. 2. On your subscription details page, expand the **Actions** menu and select **Cancel subscription**. A field displays, prompting you to add the wallet address you want to send the remaining funds to. 3. Enter your wallet address and click **Cancel subscription**. MetaMask opens and asks you to confirm the transaction. After you approve the transaction, Chainlink VRF closes your subscription account and sends the remaining LINK to your wallet. ## Vyper example You must import the `VRFCoordinatorV2` Vyper interface. You can find it [here](https://github.com/smartcontractkit/apeworx-starter-kit/blob/main/contracts/interfaces/VRFCoordinatorV2.vy). You can find a `VRFConsumerV2` example [here](https://github.com/smartcontractkit/apeworx-starter-kit/blob/main/contracts/VRFConsumerV2.vy). Read the ***apeworx-starter-kit*** [README](https://github.com/smartcontractkit/apeworx-starter-kit) to learn how to run the example. --- # Programmatic Subscription Source: https://docs.chain.link/vrf/v2/subscription/examples/programmatic-subscription How you manage the subscription depends on your randomness needs. You can configure your subscriptions using the [Subscription Manager](/vrf/v2/subscription/ui), but these examples demonstrate how to create your subscription and add your consumer contracts programmatically. For these examples, the contract owns and manages the subscription. Any wallet can provide funding to those subscriptions. You can view and monitor your subscriptions in the [Subscription Manager](/vrf/v2/subscription/ui) even if you create them programmatically. Go to [vrf.chain.link](https://vrf.chain.link) to open the Subscription Manager. ## Modifying subscriptions and configurations Subscription configurations do not have to be static. You can change your subscription configuration dynamically by calling the following functions using the [VRFCoordinatorV2Interface](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol): - Change the list of approved subscription consumers with: - `addConsumer(uint64 subId, address consumer)`. - `removeConsumer(uint64 subId, address consumer)`. - Transfer the subscription ownership with: - `requestSubscriptionOwnerTransfer(uint64 subId, address newOwner)`. - `acceptSubscriptionOwnerTransfer(uint64 subId)`. - View the subscription with `getSubscription(uint64 subId)`. - Cancel the subscription with `cancelSubscription(uint64 subId)`. To send LINK to the subscription balance, use the LINK token interface with `LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(subId))`. Any wallet can fund a subscription. See the example in the [Subscription manager contract](#subscription-manager-contract) section to learn how to create a contract that can change your subscription configuration. ## Subscription manager contract In this example, the contract operates as a subscription owner and can run functions to add consuming contracts to the subscription. The consuming contracts must include the `requestRandomWords()` function with the correct coordinator parameters and the correct subscription ID to request random values and use the subscription balance. The consuming contracts must also include the `fulfillRandomWords()` function to receive the random values. Subscription owners and consumers do not have to be separate. This contract not only allows adding consumers with `addConsumer(address consumerAddress)` but can also act as a consumer by running its own `requestRandomWords()` function. This example contract includes a `createNewSubscription()` function in the `constructor()` that creates the subscription and adds itself as a consumer automatically when you deploy it. ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that also owns and manages the subscription pragma solidity ^0.8.7; import {LinkTokenInterface} from "@chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol"; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; /** * Request testnet LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: * https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract VRFv2SubscriptionManager is VRFConsumerBaseV2 { VRFCoordinatorV2Interface COORDINATOR; LinkTokenInterface LINKTOKEN; // Sepolia coordinator. For other networks, // see https://docs.chain.link/docs/vrf-contracts/#configurations address vrfCoordinator = 0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625; // Sepolia LINK token contract. For other networks, see // https://docs.chain.link/docs/vrf-contracts/#configurations address link_token_contract = 0x779877A7B0D9E8603169DdbD7836e478b4624789; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf-contracts/#configurations bytes32 keyHash = 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c; // A reasonable default is 100000, but this value could be different // on other networks. uint32 callbackGasLimit = 100_000; // The default is 3, but you can set this higher. uint16 requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 numWords = 2; // Storage parameters uint256[] public s_randomWords; uint256 public s_requestId; uint64 public s_subscriptionId; address s_owner; constructor() VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); LINKTOKEN = LinkTokenInterface(link_token_contract); s_owner = msg.sender; //Create a new subscription when you deploy the contract. createNewSubscription(); } // Assumes the subscription is funded sufficiently. function requestRandomWords() external onlyOwner { // Will revert if subscription is not set and funded. s_requestId = COORDINATOR.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords); } function fulfillRandomWords( uint256, /* requestId */ uint256[] memory randomWords ) internal override { s_randomWords = randomWords; } // Create a new subscription when the contract is initially deployed. function createNewSubscription() private onlyOwner { s_subscriptionId = COORDINATOR.createSubscription(); // Add this contract as a consumer of its own subscription. COORDINATOR.addConsumer(s_subscriptionId, address(this)); } // Assumes this contract owns link. // 1000000000000000000 = 1 LINK function topUpSubscription( uint256 amount ) external onlyOwner { LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subscriptionId)); } function addConsumer( address consumerAddress ) external onlyOwner { // Add a consumer contract to the subscription. COORDINATOR.addConsumer(s_subscriptionId, consumerAddress); } function removeConsumer( address consumerAddress ) external onlyOwner { // Remove a consumer contract from the subscription. COORDINATOR.removeConsumer(s_subscriptionId, consumerAddress); } function cancelSubscription( address receivingWallet ) external onlyOwner { // Cancel the subscription and send the remaining LINK to a wallet address. COORDINATOR.cancelSubscription(s_subscriptionId, receivingWallet); s_subscriptionId = 0; } // Transfer this contract's funds to an address. // 1000000000000000000 = 1 LINK function withdraw( uint256 amount, address to ) external onlyOwner { LINKTOKEN.transfer(to, amount); } modifier onlyOwner() { require(msg.sender == s_owner); _; } } ``` To use this contract, compile and deploy it in Remix. 1. Open the contract in [Remix](https://remix.ethereum.org/#url=https://docs.chain.link/samples/VRF/VRFv2SubscriptionManager.sol). 2. Compile and deploy the contract using the Injected Provider environment. The contract includes all of the configuration variables that you need, but you can edit them if necessary. For a full list of available configuration variables, see the [Supported Networks](/vrf/v2/subscription/supported-networks) page. This contract automatically creates a new subscription when you deploy it. Read the `s_subscriptionId` variable to find your subscription ID. You can use this value to find the subscription at [vrf.chain.link](https://vrf.chain.link). 3. In this example, the `topUpSubscription()` function sends LINK from your contract to the subscription. Fund your contract with at least three testnet LINK. Alternatively, you can send LINK directly to the subscription at [vrf.chain.link](https://vrf.chain.link). Any address can provide funding to a subscription balance. If you need testnet LINK, you can get it from [faucets.chain.link](https://faucets.chain.link/sepolia/). 4. Run the `topUpSubscription()` function to send LINK from your contract to your subscription balance. For this example, specify a value of `3000000000000000000`, which is equivalent to three LINK. 5. Run the `requestRandomWords()` function. The request might take several minutes to process. Track the pending request status at [vrf.chain.link](https://vrf.chain.link). 6. You can also add and test consumer contracts using the same programmatic subscription process: 1. Create and deploy a consumer contract that includes the following components: - The `requestRandomWords()` function and the required variables and your subscription ID. - The `fulfillRandomWords()` callback function. You can use the example from the [Get a Random Number](/vrf/v2/subscription/examples/get-a-random-number/#analyzing-the-contract) guide. 2. After you deploy the consumer contract, add it to the subscription as an approved consumer using the `addConsumer()` function on your subscription manager contract. Specify the address of your consumer contract. 3. On the consumer contract, run the `requestRandomWords()` function to request and receive random values. The request might take several minutes to process. Track the pending request status at [vrf.chain.link](https://vrf.chain.link). The consumer contract can continue to make requests until your subscription balance runs out. The subscription manager contract must maintain sufficient balance in the subscription so that the consumers can continue to operate. 4. If you need to remove consumer contracts from the subscription, use the `removeConsumer()` function. Specify the address of the consumer contract to be removed. 7. When you are done with your contracts and the subscription, run the `cancelSubscription()` function to close the subscription and send the remaining LINK to your wallet address. Specify the address of the receiving wallet. ## Funding and requesting simultaneously You can fund a subscription and request randomness in a single transaction. You must estimate how much the transaction might cost and determine the amount of funding to send to the subscription yourself. See the [Subscription billing](/vrf/v2/subscription/#subscription-limits) page to learn how to estimate request costs. ```sol // Assumes this contract owns link // You must estimate LINK cost yourself based on the gas lane and limits. // 1_000_000_000_000_000_000 = 1 LINK function fundAndRequestRandomWords(uint256 amount) external onlyOwner { LINKTOKEN.transferAndCall( address(COORDINATOR), amount, abi.encode(s_subscriptionId) ); // Will revert if subscription is not set and funded. s_requestId = COORDINATOR.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords ); } ``` Add this function to your contracts if you need to provide funding simultaneously with your requests. The `transferAndCall()` function sends LINK from your contract to the subscription, and the `requestRandomWords()` function requests the random words. Your contract still needs the `fulfillRandomWords()` callback function to receive the random values. --- # Local testing using a Mock contract Source: https://docs.chain.link/vrf/v2/subscription/examples/test-locally > **TIP: VRF V2.5 Subscription Mock Tutorial** > > Refer to the [VRF V2.5 version of this subscription mock tutorial](/vrf/v2-5/subscription/test-locally) to learn how > to test locally with VRF V2.5. To compare V2.5 and V2, refer to the [migration guide](/vrf/v2-5/migration-from-v2). This guide explains how to test Chainlink VRF v2 on a [Remix IDE](https://remix-ide.readthedocs.io/en/latest/run.html#environment) sandbox blockchain environment. **Note**: You can reuse the same logic on another development environment, such as Hardhat or Truffle. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js). > **CAUTION: Test on public testnets thoroughly** > > Even though local testing has several benefits, testing with a VRF mock covers the bare minimum of use cases. Make > sure to test your consumer contract thoroughly on public testnets. ## Benefits of local testing ## Testing logic Complete the following tasks to test your VRF v2 consumer locally: 1. Deploy the [VRFCoordinatorV2Mock](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol). This contract is a mock of the [VRFCoordinatorV2](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol) contract. 2. Call the VRFCoordinatorV2Mock [createSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L194) to create a new subscription. 3. Call the VRFCoordinatorV2Mock [fundSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L156) to fund your newly created subscription. **Note**: You can fund with an arbitrary amount. 4. Deploy your VRF consumer contract. 5. Call the VRFCoordinatorV2Mock [addConsumer function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L230) to add your consumer contract to your subscription. 6. Request random words from your consumer contract. 7. Call the VRFCoordinatorV2Mock [fulfillRandomWords function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L108) to fulfill your consumer contract request. ## Testing ### Open the contracts on RemixIDE Open *VRFCoordinatorV2Mock* and compile in Remix: ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol"; ``` Open *VRFv2Consumer* and compile in Remix: ```sol // SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.7; import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol"; import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol"; /** * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ /** * @title The RandomNumberConsumerV2 contract * @notice A contract that gets random values from Chainlink VRF V2 */ contract RandomNumberConsumerV2 is VRFConsumerBaseV2 { VRFCoordinatorV2Interface immutable COORDINATOR; // Your subscription ID. uint64 immutable s_subscriptionId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf-contracts/#configurations bytes32 immutable s_keyHash; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 constant CALLBACK_GAS_LIMIT = 100_000; // The default is 3, but you can set this higher. uint16 constant REQUEST_CONFIRMATIONS = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. uint32 constant NUM_WORDS = 2; uint256[] public s_randomWords; uint256 public s_requestId; address s_owner; event ReturnedRandomness(uint256[] randomWords); /** * @notice Constructor inherits VRFConsumerBaseV2 * * @param subscriptionId - the subscription ID that this contract uses for funding requests * @param vrfCoordinator - coordinator, check https://docs.chain.link/docs/vrf-contracts/#configurations * @param keyHash - the gas lane to use, which specifies the maximum gas price to bump to */ constructor( uint64 subscriptionId, address vrfCoordinator, bytes32 keyHash ) VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_keyHash = keyHash; s_owner = msg.sender; s_subscriptionId = subscriptionId; } /** * @notice Requests randomness * Assumes the subscription is funded sufficiently; "Words" refers to unit of data in Computer Science */ function requestRandomWords() external onlyOwner { // Will revert if subscription is not set and funded. s_requestId = COORDINATOR.requestRandomWords(s_keyHash, s_subscriptionId, REQUEST_CONFIRMATIONS, CALLBACK_GAS_LIMIT, NUM_WORDS); } /** * @notice Callback function used by VRF Coordinator * * @param - id of the request * @param randomWords - array of random results from VRF Coordinator */ function fulfillRandomWords( uint256, /* requestId */ uint256[] memory randomWords ) internal override { s_randomWords = randomWords; emit ReturnedRandomness(randomWords); } modifier onlyOwner() { require(msg.sender == s_owner); _; } } ``` Your RemixIDE file explorer should display *VRFCoordinatorV2Mock.sol* and *VRFv2Consumer.sol*: ![Image](/images/vrf/mock/v2-subscription-remix-fileexplorer.jpg) ### Deploy VRFCoordinatorV2Mock 1. Open *VRFCoordinatorV2Mock.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *VRFCoordinatorV2Mock*. ![Image](/images/vrf/mock/v2-deploymock.jpg) 3. Under *DEPLOY*, fill in the `_BASEFEE` and `_GASPRICELINK`. These variables are used in the *VRFCoordinatorV2Mock* contract to represent the base fee and the gas price (in LINK tokens) for the VRF requests. You can set: `_BASEFEE=100000000000000000` and `_GASPRICELINK=1000000000`. 4. Click on *transact* to deploy the *VRFCoordinatorV2Mock* contract. 5. Once deployed, you should see the *VRFCoordinatorV2Mock* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedmock.jpg) 6. Note the address of the deployed contract. ### Create and fund a subscription 1. Click on `createSubscription` to create a new subscription. 2. In the RemixIDE console, read your transaction decoded output to find the subscription ID. In this example, the subscription ID is *1*. ![Image](/images/vrf/mock/v2-mocksubscription.jpg) 3. Click on `fundSubscription` to fund your subscription. In this example, you can set the `_subid` to `1` (which is your newly created subscription ID) and the `_amount` to `1000000000000000000`. ### Deploy the VRF consumer contract 1. In the file explorer, open *VRFv2Consumer.sol*. 2. Under *DEPLOY & RUN TRANSACTIONS*, select *RandomNumberConsumerV2*. ![Image](/images/vrf/mock/v2-deployconsumer.jpg) 3. Under *DEPLOY*, fill in `SUBSCRIPTIONID` with your subscription ID, `vrfCoordinator` with the deployed *VRFCoordinatorV2Mock* address and, *KEYHASH* with an arbitrary `bytes32` (In this example, you can set the *KEYHASH* to `0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc`). 4. Click on *transact* to deploy the *RandomNumberConsumerV2* contract. 5. After the consumer contract is deployed, you should see the *RandomNumberConsumerV2* contract under *Deployed Contracts*. ![Image](/images/vrf/mock/v2-deployedconsumer.jpg) 6. Note the address of the deployed contract. ### Add the consumer contract to your subscription 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract. 2. Click on *addConsumer* and fill in the `_subid` with your subscription ID and `_consumer` with your deployed consumer contract address. ![Image](/images/vrf/mock/v2-addconsumer.jpg) 3. Click on *transact*. ### Request random words 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2* contract. 2. Click on `requestRandomWords`. ![Image](/images/vrf/mock/v2-requestrandomwords.jpg) 3. In the RemixIDE console, read your transaction logs to find the VRF request ID. In this example, the request ID is *1*. ![Image](/images/vrf/mock/v2-requestrandomwordslogs.jpg) 4. Note your request ID. ### Fulfill the VRF request Because you are testing on a local blockchain environment, you must fulfill the VRF request yourself. 1. Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract. 2. Click `fulfillRandomWords` and fill in `_requestId` with your VRF request ID and `_consumer` with your consumer contract address. ![Image](/images/vrf/mock/v2-fulfillrandomwords.jpg) 3. Click on `transact`. ### Check the results 1. Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2* contract. 2. Click on `s_requestId` to display the last request ID. In this example, the output is *1*. ![Image](/images/vrf/mock/v2-deployedconsumerrequestid.jpg) 3. Each time you make a VRF request, your consumer contract requests two random words. After the request is fulfilled, the two random words are stored in the `s_randomWords` array. You can check the stored random words by reading the two first indexes of the `s_randomWords` array. To do so, click on the *s_randomWords* function and: 1. Fill in the index with *0* then click on *call* to read the first random word. ![Image](/images/vrf/mock/v2-firstrandomword.jpg) 2. Fill in the index with *1* then click on *call* to read the second random word. ![Image](/images/vrf/mock/v2-secondrandomword.jpg) ## Next steps This guide demonstrated how to test a VRF v2 consumer contract on your local blockchain. We made the guide on RemixIDE for learning purposes, but you can reuse the same [testing logic](#testing-logic) on another development environment, such as Truffle or Hardhat. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js). --- # Supported Networks - Subscription Method Source: https://docs.chain.link/vrf/v2/subscription/supported-networks Chainlink VRF allows you to integrate provably fair and verifiably random data in your smart contract. For implementation details, read [Introduction to Chainlink VRF](/vrf). ## Coordinator parameters These parameters are configured in the coordinator contract. You can view these values by running `getConfig` on the coordinator or by viewing the coordinator contracts in a blockchain explorer. - `uint16 minimumRequestConfirmations`: The minimum number of confirmation blocks on VRF requests before oracles respond - `uint32 maxGasLimit`: The maximum gas limit supported for a `fulfillRandomWords` callback. - `uint32 stalenessSeconds`: How long the coordinator waits until we consider the ETH/LINK price used for converting gas costs to LINK is stale and use `fallbackWeiPerUnitLink` - `uint32 gasAfterPaymentCalculation`: How much gas is used outside of the payment calculation. This covers the additional operations required to decrement the subscription balance and increment the balance for the oracle that handled the request. ## Fee parameters Fee parameters are configured in the coordinator contract and specify the premium you pay per request in addition to the gas cost for the transaction. You can view them by running `getFeeConfig` on the coordinator. The `uint32 fulfillmentFlatFeeLinkPPMTier1` parameter defines the fees per request specified in millionths of LINK. The details for calculating the total transaction cost can be found [here](/vrf/v2/subscription/#request-and-receive-data). ## Configurations VRF v2 coordinators for subscription funding are available on several networks. To see a list of coordinators for direct funding, see the [Direct Funding Configurations](/vrf/v2/direct-funding/supported-networks) page. To use Chainlink VRF on certain networks, you may need to conduct token transfers. You can transfer tokens by using [Chainlink CCIP](/ccip/tutorials/evm/transfer-tokens-from-contract), [Transporter](https://www.transporter.io/) or third-party applications such as [XSwap](https://xswap.link/). > **NOTE: Interfaces and Applications** > > Chainlink CCIP is a messaging protocol. Third parties may build user interfaces or other applications on top of CCIP. > Neither Chainlink Labs nor the Chainlink Foundation owns, controls, endorses, or assumes any responsibility for any > such interfaces or applications. You are solely responsible for your use of such interfaces or applications. Please > visit the Chainlink Foundation [Terms of Service](https://chain.link/terms) for more information. > **CAUTION: Understand Risks associated with Bridges** > > If you are using a cross-chain bridge to transfer your LINK tokens, read the [Bridges and Associated Risks](/resources/bridge-risks) guide to understand what cross-chain bridges are and the risks associated with using them. ### Ethereum mainnet | Item | Value | | --------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x514910771AF9Ca656af840dff83E8264EcF986CA](https://etherscan.io/token/0x514910771AF9Ca656af840dff83E8264EcF986CA) | | VRF Coordinator | [0x271682DEB8C4E0901D1a1550aD2e64D568E69909](https://etherscan.io/address/0x271682DEB8C4E0901D1a1550aD2e64D568E69909) | | 200 gwei Key Hash | 0x8af398995b04c28e9951adb9721ef74c74f93e6a478f39e7e0777be13527e7ef | | 500 gwei Key Hash | 0xff8dedfbfa60af186cf3c830acbc32c05aae823045ae5ea7da1e45fbfaba4f92 | | 1000 gwei Key Hash | 0x9fe0eebf5e446e3c998ec9bb19951541aee00bb90ea201ae456421a2ded86805 | | Premium | 0.25 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Sepolia testnet Testnet LINK and ETH are available from [faucets.chain.link](https://faucets.chain.link/sepolia). Testnet ETH is also available from several public [ETH faucets](https://faucetlink.to/sepolia). | Item | Value | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x779877A7B0D9E8603169DdbD7836e478b4624789](https://sepolia.etherscan.io/token/0x779877A7B0D9E8603169DdbD7836e478b4624789) | | VRF Coordinator | [0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625](https://sepolia.etherscan.io/address/0x8103B0A8A00be2DDC778e6e7eaa21791Cd364625) | | 750 gwei Key Hash | 0x474e34a077df58807dbe9c96d3c009b23b3c6d0cce433e59bbf5b34f823bc56c | | Premium | 0.25 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### BNB Chain mainnet > **TIP: Important** > > The LINK provided by the [BNB Chain Bridge](https://www.bnbchain.world/en/bridge) is not ERC-677 compatible, so cannot > be used with Chainlink oracles. However, it can be [**converted to the official LINK token on BNB Chain using > Chainlink's PegSwap service**](https://pegswap.chain.link/). | Item | Value | | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x404460C6A5EdE2D891e8297795264fDe62ADBB75](https://bscscan.com/token/0x404460C6A5EdE2D891e8297795264fDe62ADBB75) | | VRF Coordinator | [0xc587d9053cd1118f25F645F9E08BB98c9712A4EE](https://bscscan.com/address/0xc587d9053cd1118f25F645F9E08BB98c9712A4EE) | | 200 gwei Key Hash | 0x114f3da0a805b6a67d6e9cd2ec746f7028f1b7376365af575cfea3550dd1aa04 | | 500 gwei Key Hash | 0xba6e730de88d94a5510ae6613898bfb0c3de5d16e609c5b7da808747125506f7 | | 1000 gwei Key Hash | 0x17cd473250a9a479dc7f234c64332ed4bc8af9e8ded7556aa6e66d83da49f470 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### BNB Chain testnet Testnet LINK is available from [https://faucets.chain.link/bnb-chain-testnet](https://faucets.chain.link/bnb-chain-testnet) | Item | Value | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06](https://testnet.bscscan.com/address/0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06) | | VRF Coordinator | [0x6A2AAd07396B36Fe02a22b33cf443582f682c82f](https://testnet.bscscan.com/address/0x6A2AAd07396B36Fe02a22b33cf443582f682c82f) | | 50 gwei Key Hash | 0xd4bb89654db74673a187bd804519e65e3f71a52bc55f11da7601a13dcf505314 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Polygon mainnet > **TIP: Important** > > The LINK provided by the [Polygon Bridge](https://wallet.polygon.technology/polygon/bridge) is not ERC-677 compatible, > so cannot be used with Chainlink oracles. However, it can be [**converted to the official LINK token on Polygon using > Chainlink's PegSwap service**](https://pegswap.chain.link/) | Item | Value | | --------------------- | ------------------------------------------------------------------------------------------------------------------------ | | LINK Token | [0xb0897686c545045aFc77CF20eC7A532E3120E0F1](https://polygonscan.com/address/0xb0897686c545045aFc77CF20eC7A532E3120E0F1) | | VRF Coordinator | [0xAE975071Be8F8eE67addBC1A82488F1C24858067](https://polygonscan.com/address/0xAE975071Be8F8eE67addBC1A82488F1C24858067) | | 200 gwei Key Hash | 0x6e099d640cde6de9d40ac749b4b594126b0169747122711109c9985d47751f93 | | 500 gwei Key Hash | 0xcc294a196eeeb44da2888d17c0625cc88d70d9760a69d58d853ba6581a9ab0cd | | 1000 gwei Key Hash | 0xd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a8 | | Premium | 0.0005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Polygon Amoy testnet | Item | Value | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904](https://amoy.polygonscan.com/address/0x0fd9e8d3af1aaee056eb9e802c3a762a667b1904) | | VRF Coordinator | [0x7E10652Cb79Ba97bC1D0F38a1e8FaD8464a8a908](https://amoy.polygonscan.com/address/0x7E10652Cb79Ba97bC1D0F38a1e8FaD8464a8a908) | | 500 gwei Key Hash | 0x3f631d5ec60a0ce16203bcd6aff7ffbc423e22e452786288e172d467354304c8 | | Premium | 0.0005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 3 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Avalanche mainnet | Item | Value | | --------------------- | --------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x5947BB275c521040051D82396192181b413227A3](https://snowtrace.io/address/0x5947BB275c521040051D82396192181b413227A3) | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://snowtrace.io/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | 200 gwei Key Hash | 0x83250c5584ffa93feb6ee082981c5ebe484c865196750b39835ad4f13780435d | | 500 gwei Key Hash | 0x89630569c9567e43c4fe7b1633258df9f2531b62f2352fa721cf3162ee4ecb46 | | 1000 gwei Key Hash | 0x06eb0e2ea7cca202fc7c8258397a36f33d88568d2522b37aaa3b14ff6ee1b696 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Avalanche Fuji testnet Testnet LINK is available from [https://faucets.chain.link/fuji](https://faucets.chain.link/fuji) | Item | Value | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846](https://testnet.snowtrace.io/address/0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846) | | | | | VRF Coordinator | [0x2eD832Ba664535e5886b75D64C46EB9a228C2610](https://testnet.snowtrace.io/address/0x2eD832Ba664535e5886b75D64C46EB9a228C2610) | | 300 gwei Key Hash | 0x354d2f95da55398f44b7cff77da56283d9c6c829a4bdf1bbcaf2ad6a4d081f61 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Fantom mainnet > **NOTE: New Fantom subscriptions not supported** > > Creating new Fantom subscriptions in the Subscription Manager is no longer supported in VRF V2 and is not supported in > VRF V2.5. Existing Fantom subscriptions are still supported. > **TIP: Important** > > You must use ERC-677 LINK on Fantom. ERC-20 LINK will not work with Chainlink services. | Item | Value | | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0x6F43FF82CCA38001B6699a8AC47A2d0E66939407](https://ftmscan.com/token/0x6F43FF82CCA38001B6699a8AC47A2d0E66939407) | | | | | VRF Coordinator | [0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634](https://ftmscan.com/address/0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634) | | 4000 gwei Key Hash | 0xb4797e686f9a1548b9a2e8c68988d74788e0c4af5899020fb0c47784af76ddfa | | 10000 gwei Key Hash | 0x5881eea62f9876043df723cf89f0c2bb6f950da25e9dfe66995c24f919c8f8ab | | 20000 gwei Key Hash | 0x64ae04e5dba58bc08ba2d53eb33fe95bf71f5002789692fe78fb3778f16121c9 | | Premium | 0.0005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Fantom testnet Testnet LINK is available from [https://faucets.chain.link/fantom-testnet](https://faucets.chain.link/fantom-testnet) | Item | Value | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F](https://testnet.ftmscan.com/address/0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F) | | | | | VRF Coordinator | [0xbd13f08b8352A3635218ab9418E340c60d6Eb418](https://testnet.ftmscan.com/address/0xbd13f08b8352A3635218ab9418E340c60d6Eb418) | | 3000 gwei Key Hash | 0x121a143066e0f2f08b620784af77cccb35c6242460b4a8ee251b4b416abaebd4 | | Premium | 0.0005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Arbitrum mainnet | Item | Value | | --------------------- | -------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xf97f4df75117a78c1A5a0DBb814Af92458539FB4](https://arbiscan.io/address/0xf97f4df75117a78c1A5a0DBb814Af92458539FB4) | | | | | VRF Coordinator | [0x41034678D6C633D8a95c75e1138A360a28bA15d1](https://arbiscan.io/address/0x41034678D6C633D8a95c75e1138A360a28bA15d1) | | 2 gwei Key Hash | 0x08ba8f62ff6c40a58877a106147661db43bc58dabfb814793847a839aa03367f | | 30 gwei Key Hash | 0x72d2b016bb5b62912afea355ebf33b91319f828738b111b723b78696b9847b63 | | 150 gwei Key Hash | 0x68d24f9a037a649944964c2a1ebd0b2918f4a243d2a99701cc22b548cf2daff0 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | ### Arbitrum Sepolia testnet Testnet LINK is available from [https://faucets.chain.link/arbitrum-sepolia](https://faucets.chain.link/arbitrum-sepolia) | Item | Value | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | LINK Token | [0xb1D4538B4571d411F07960EF2838Ce337FE1E80E](https://sepolia.arbiscan.io/address/0xb1D4538B4571d411F07960EF2838Ce337FE1E80E) | | | | | VRF Coordinator | [0x50d47e4142598E3411aA864e08a44284e471AC6f](https://sepolia.arbiscan.io/address/0x50d47e4142598E3411aA864e08a44284e471AC6f) | | 50 gwei Key Hash | 0x027f94ff1465b3525f9fc03e9ff7d6d2c0953482246dd6ae07570c45d6631414 | | Premium | 0.005 LINK | | Max Gas Limit | 2,500,000 | | Minimum Confirmations | 1 | | Maximum Confirmations | 200 | | Maximum Random Values | 500 | --- # Subscription Manager User Interface Source: https://docs.chain.link/vrf/v2/subscription/ui The [VRF Subscription Manager](https://vrf.chain.link/) is available to help you create and manage VRF subscriptions. You can create and manage new V2.5 subscriptions, and manage existing V2 subscriptions, but you can no longer create new V2 subscriptions in the VRF Subscription Manager. Alternatively, you can [create and manage V2 subscriptions programmatically](/vrf/v2/subscription/examples/programmatic-subscription). This guide walks you through the main sections of the UI. > **TIP: Troubleshooting** > > Read the [pending](#pending) and [failed requests](#failed-requests) sections to learn how to troubleshoot your VRF > requests. ![VRF v2 UI overview](/images/vrf/v2-ui-overview.png) Subscription components: - **Status**: Indicates if the subscription is still active or not. - **ID**: The unique subscription identifier. Approved consuming contracts use LINK from this subscription to pay for each randomness request. - **Admin**: The account address that owns this subscription ID. - **Consumers**: The number of consuming contracts that are approved to make VRF requests using this subscription. - **Fulfillment**: The number of successful randomness requests that are already completed. - **Balance**: The amount of LINK remaining to be used for requests that use this subscription. ## Actions menu Expand the **Actions** menu to display actions you can take for any subscription that you own: ![VRF v2 UI with Actions menu expanded](/images/vrf/v2-ui-overview-actions-expanded.png) - **Fund subscription**: Displays a field allowing you to fund your subscription from your connected wallet. Specify how much LINK you'd like to send to your subscription. - **Add email address**: Displays a field allowing you to add an email address to your subscription. This is an optional field. - **Cancel subscription**: Displays a field allowing you to specify the account address to receive the remaining balance. See the clean up instructions in the [Get a Random Number](/vrf/v2/subscription/examples/get-a-random-number/#clean-up) guide to learn more. Note: It is possible to fund subscriptions that you do not own. In that case, the Actions menu displays only the **Fund subscription** option. ## Consumers ![VRF v2 UI consumers](/images/vrf/v2-ui-consumers.png) The **Consumers** section lists the contracts that are allowed to use your subscription to pay for requests. - **Address**: The address of the consuming contract. - **Added**: The time when the consumer was added to the subscription. - **Last fulfillment**: The last time a VRF request was fulfilled for the consumer. - **Total spent**: The total amount of LINK that has been used by the consuming contract. You can use this section to add or remove consumers. ## Pending ![VRF v2 UI pending](/images/vrf/v2-ui-pending.png) The **Pending** list appears if there are requests currently being processed. - **Time**: The time when the pending VRF request was made. - **Consumer**: The address of the consuming contract. - **Transaction hash**: The transaction hash of the pending VRF request. - **Status**: A timer that informs you when the pending VRF request will move to a failed status. **Note**: Pending requests fail after 24h. - **Max Cost**: The estimated upper limit of the transaction cost in LINK based on the configuration. Learn more about the [minimum subscription balance](/vrf/v2/subscription/#minimum-subscription-balance). - **Projected Balance**: This indicates when the subscription is underfunded and how many LINK tokens are required to fund the subscription. ## History ### Recent fulfillments ![VRF v2 UI recent fulfill](/images/vrf/v2-ui-recent-fulfill.png) The **Recent fulfillments** tab shows the details for successful VRF fulfillments. - **Time**: The time and block number indicating when the VRF request was successfully fulfilled. - **Consumer**: The address of the consuming contract that initiated the VRF request. - **Transaction Hash**: The transaction hash of the VRF callback. - **Status**: The status of the request. Recent fulfillments always show *Success*. - **Spent**: The total amount of LINK spent to fulfill the VRF request. - **Balance**: The LINK balance of the subscription after the VRF request was fulfilled. ### Events ![VRF v2 ui history events](/images/vrf/v2-ui-history-events.png) The **Events** tab displays events linked to the subscription. There are five main events: - Subscription created - Subscription funded - Consumer added - Consumer removed - Subscription canceled Components of VRF events: - **Time**: The time when the event happened. - **Event**: The type of the event. - **Transaction Hash**: The transaction hash for the event. - **Consumer**: The address of the consuming contract. This is used only for *Consumer added* and *Consumer canceled* events. - **Amount**: - For *Subscription funded* events, this indicates the amount of LINK added to the subscription balance. - For *Subscription canceled* events, this indicates the amount of LINK withdrawn from the subscription balance. - **Balance**: - For *Subscription funded* events, this indicates the LINK balance of the subscription after it was funded. - For *Subscription canceled* events, this field should display *0*. ### Failed requests ![VRF v2 UI history failed](/images/vrf/v2-ui-history-failed.png) The **Failed requests** tab displays failed VRF requests. - **Time**: The time when the VRF request was made. - **Transaction Hash**: This can be either the transaction hash of the originating VRF request if the request was pending for over 24 hours *or* the transaction hash of the VRF callback if the callback failed. - **Status**: The status of the request. Failed requests always show *Failed*. - **Reason**: The reason why the request failed. Requests fail for one of the following reasons: - Pending for over 24 hours - Wrong key hash specified - Callback gas limit set too low