Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc VRF updates #1921

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Binary file added public/images/vrf/v2-5-migration.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/vrf/vrf-diagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 65 additions & 62 deletions src/config/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,18 +741,8 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
section: "Chainlink VRF v2.5",
contents: [
{
title: "V2.5 Overview",
title: "Introduction to VRF",
url: "vrf",
children: [
{
title: "Subscription overview",
url: "vrf/v2-5/overview/subscription",
},
{
title: "Direct funding overview",
url: "vrf/v2-5/overview/direct-funding",
},
],
},
{
title: "Migration from V2",
Expand All @@ -774,75 +764,52 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
title: "V2.5 Billing",
url: "vrf/v2-5/billing",
},
{
title: "Create and manage V2.5 subscriptions",
url: "vrf/v2-5/subscription/create-manage",
},
{
title: "Release Notes",
url: "vrf/release-notes",
},
{
title: "Arbitrum gas estimation with VRF",
url: "vrf/v2-5/arbitrum-cost-estimation",
},
],
},
{
section: "V2 Subscription Method",
section: "Learn VRF V2.5",
contents: [
{
title: "Introduction",
url: "vrf/v2/subscription",
},
{
title: "Get a Random Number",
url: "vrf/v2/subscription/examples/get-a-random-number",
},
{
title: "Programmatic Subscription",
url: "vrf/v2/subscription/examples/programmatic-subscription",
},
{
title: "Test Locally Using a Mock Contract",
url: "vrf/v2/subscription/examples/test-locally",
title: "Introduction to subscription",
url: "vrf/v2-5/overview/subscription",
},
{
title: "Subscription Manager UI",
url: "vrf/v2/subscription/ui",
title: "Introduction to direct funding",
url: "vrf/v2-5/overview/direct-funding",
},
{
title: "Supported Networks",
url: "vrf/v2/subscription/supported-networks",
},
{
title: "Migrating from VRF v1",
url: "vrf/v2/subscription/migration-from-v1",
title: "Arbitrum gas estimation with VRF",
url: "vrf/v2-5/arbitrum-cost-estimation",
},
],
},
{
section: "V2 Direct Funding Method",
section: "Build with VRF 2.5",
contents: [
{
title: "Introduction",
url: "vrf/v2/direct-funding",
},
{
title: "Get a Random Number",
url: "vrf/v2/direct-funding/examples/get-a-random-number",
title: "Create and manage V2.5 subscriptions",
url: "vrf/v2-5/subscription/create-manage",
},
{
title: "Test Locally Using a Mock Contract",
url: "vrf/v2/direct-funding/examples/test-locally",
title: "Migrate from VRF v1",
url: "vrf/v2-5/migration-from-v1",
},
],
},
{
section: "All VRF V2 documentation",
contents: [
{
title: "Supported Networks",
url: "vrf/v2/direct-funding/supported-networks",
title: "VRF V2 Subscription",
url: "vrf/v2/subscription",
},
{
title: "Migrating from VRF v1",
url: "vrf/v2/direct-funding/migration-from-v1",
title: "VRF V2 Direct Funding",
url: "vrf/v2/direct-funding",
},
],
},
Expand Down Expand Up @@ -1435,17 +1402,53 @@ export const SIDEBAR: Partial<Record<Sections, SectionEntry[]>> = {
],
legacy: [
{
section: "VRF v1 [DEPRECATED]",
section: "V2 Subscription Method",
contents: [
{ title: "Introduction to Chainlink VRF", url: "vrf/v1/introduction" },
{
title: "Introduction",
url: "vrf/v2/subscription",
},
{
title: "Get a Random Number",
url: "vrf/v1/examples/get-a-random-number",
url: "vrf/v2/subscription/examples/get-a-random-number",
},
{
title: "Programmatic Subscription",
url: "vrf/v2/subscription/examples/programmatic-subscription",
},
{
title: "Test Locally Using a Mock Contract",
url: "vrf/v2/subscription/examples/test-locally",
},
{
title: "Subscription Manager UI",
url: "vrf/v2/subscription/ui",
},
{
title: "Supported Networks",
url: "vrf/v2/subscription/supported-networks",
},
],
},
{
section: "V2 Direct Funding Method",
contents: [
{
title: "Introduction",
url: "vrf/v2/direct-funding",
},
{
title: "Get a Random Number",
url: "vrf/v2/direct-funding/examples/get-a-random-number",
},
{
title: "Test Locally Using a Mock Contract",
url: "vrf/v2/direct-funding/examples/test-locally",
},
{
title: "Supported Networks",
url: "vrf/v2/direct-funding/supported-networks",
},
{ title: "Security Considerations", url: "vrf/v1/security" },
{ title: "Best Practices", url: "vrf/v1/best-practices" },
{ title: "Supported Networks", url: "vrf/v1/supported-networks" },
{ title: "API Reference", url: "vrf/v1/api-reference" },
],
},
{
Expand Down
7 changes: 5 additions & 2 deletions src/content/vrf/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ metadata:
---

import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro"
import { Aside } from "@components"
import { Aside, ClickToZoom } from "@components"

<VrfCommon callout="security" />

Expand All @@ -28,13 +28,16 @@ Use Chainlink VRF to build reliable smart contracts for any applications that re
- 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:
[VRF v2.5](https://blog.chain.link/introducing-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.
- Gas optimization

Learn how to [migrate to VRF v2.5](/vrf/v2-5/migration-from-v2).

<ClickToZoom src="/images/vrf/vrf-diagram.png" alt="Chainlink VRF Diagram" />

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
Expand Down
173 changes: 173 additions & 0 deletions src/content/vrf/v2-5/migration-from-v1.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
---
section: vrf
date: Last Modified
title: "Migrate from VRF v1"
---

import { Aside } from "@components"
import { Tabs, TabsContent } from "@components/Tabs"

## Comparison between VRF v1 and VRF v2.5

For a more similar payment experience to V1, use the direct funding method.
Otherwise, you can fund a subscription to prepay for VRF requests. In both cases, VRF V2.5 allows you the option to pay in either native tokens or LINK.

{/* prettier-ignore */}
<TabsContent sharedStore="vrfMethod" client:visible>
<Fragment slot="tab.1">Subscription</Fragment>
<Fragment slot="tab.2">Direct funding</Fragment>
<Fragment slot="panel.1">
Chainlink VRF v2.5 includes several improvements and changes to the way you fund and request randomness for your smart contracts.

- **Subscription management:** Chainlink VRF v2.5 introduces a [Subscription Manager](https://vrf.chain.link) application that allows smart contract applications to pre-fund multiple requests for randomness using either a LINK token balance or a native token balance. This reduces the gas fees for VRF requests by eliminating the need to transfer tokens for each individual request. You transfer tokens to the subscription balance only when it requires additional funding.

- **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 V2.5 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:** The [VRF Coordinator contracts](/vrf/v2-5/supported-networks) in VRF v2.5 allow you to 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.

- **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, which is managed by the subscription owner. Your subscription has balances for LINK and for native tokens.

</Fragment>
<Fragment slot="panel.2">

The main similarity between VRF v1 and the VRF v2.5 Direct funding method is that consuming contracts must be funded to pay for requests. However, Chainlink VRF v2.5 includes several improvements:

- **Native token billing:** Chainlink VRF v2.5 lets you fund your consuming contract with either LINK or native tokens to pay for VRF requests.

- **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 that you use. See the gas limits on the [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:** The [VRF Wrapper contracts](/vrf/v2-5/supported-networks) in VRF v2.5 allow you to 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.

</Fragment>
</TabsContent>

## Updating your applications to use VRF v2

{/* prettier-ignore */}
<TabsContent sharedStore="vrfMethod" client:visible>
<Fragment slot="tab.1">Subscription</Fragment>
<Fragment slot="tab.2">Direct funding</Fragment>
<Fragment slot="panel.1">
To modify your existing smart contract code to work with VRF v2.5, complete the following changes. See the [Migration from V2](/vrf/v2-5/migration-from-v2#compare-example-code) guide for an example.

1. Set up and fund a subscription in the Subscription Manager at [vrf.chain.link](https://vrf.chain.link).
{/* prettier-ignore */}

<div class="remix-callout">
<a href="https://vrf.chain.link">Open the Subscription Manager</a>
</div>

1. Import the [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) contract and remove the v1 `VRFConsumerBase.sol` import. This contract includes the `fulfillRandomWords` function.

1. Import the VRF v2.5 coordinator, [`VRFCoordinatorV2_5`](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol). This interface includes the new `requestRandomWords` function.

1. Add a `VRFConsumerBaseV2Plus` constructor, passing in the LINK token address for the network you're using.

1. Change `requestRandomness` function calls to `requestRandomWords`. The `requestRandomWords` function requires several additional parameters. Make sure to include the `extraArgs` part of the `VRFV2PlusClient.RandomWordsRequest` mapping, and use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens:

{/* prettier-ignore */}
<Tabs sharedStore="feePaymentType" client:visible>
<Fragment slot="tab.1">LINK</Fragment>
<Fragment slot="tab.2">Native tokens</Fragment>
<Fragment slot="panel.1">
{/* prettier-ignore */}
```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}))
})
);
```
</Fragment>
<Fragment slot="panel.2">
{/* prettier-ignore */}
```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}))
})
);
```
</Fragment>
</Tabs>

1. Change `fulfillRandomness` function calls to `fulfillRandomWords`. Update the call to handle the returned `uint256[]` array instead of the single `uint256` variable.

</Fragment>
<Fragment slot="panel.2">

To modify your existing smart contract code to work with VRF v2, complete the following changes. See the [Migration from V2](/vrf/v2-5/migration-from-v2#compare-example-code) guide for an example.

<Aside type="caution" title="Outdated V2.5 direct funding interface and wrapper in chainlink 1.1.0 package">
The [`chainlink/contracts` 1.1.0 package](https://www.npmjs.com/package/@chainlink/contracts/v/1.1.0) currently has an outdated interface and wrapper for V2.5 direct funding. If you deploy contracts for direct funding with these outdated interfaces, your `requestRandomness` function will revert.

Use this interface and wrapper:

- `VRFV2PlusWrapperConsumerBase.sol`: https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol
- `IVRFV2PlusWrapper.sol`: https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol

</Aside>

1. Import and inherit the new [`VRFV2PlusWrapperConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) and remove the v1 `VRFConsumerBase.sol` import. This contract includes the `fulfillRandomWords` function.

1. Add a `VRFV2WrapperConsumerBase` constructor, passing in the VRF wrapper address for the network you're using.

1. You can still call the `requestRandomness` function. However, the v2.5 `requestRandomness` function requires several different parameters (`callbackGasLimit` , `requestConfirmations` , `numWords` and `extraArgs`). See the [Supported networks](/vrf/v2-5/supported-networks) page to adjust them for your own needs.

Use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens:

{/* prettier-ignore */}
<Tabs sharedStore="feePaymentType" client:visible>
<Fragment slot="tab.1">LINK</Fragment>
<Fragment slot="tab.2">Native tokens</Fragment>
<Fragment slot="panel.1">

{/* prettier-ignore */}
```solidity
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: false})
);
(uint256 reqId, uint256 reqPrice) = requestRandomness(
callbackGasLimit,
requestConfirmations,
numWords,
extraArgs
);
```

</Fragment>
<Fragment slot="panel.2">

{/* prettier-ignore */}
```solidity
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({nativePayment: true})
);
(uint256 reqId, uint256 reqPrice) = requestRandomness(
callbackGasLimit,
requestConfirmations,
numWords,
extraArgs
);
```
</Fragment>
</Tabs>

1. Change `fulfillRandomness` function calls to `fulfillRandomWords`. Update the call to handle the returned `uint256[]` array instead of the single `uint256` variable.

</Fragment>
</TabsContent>