diff --git a/public/samples/VRF/v2-5/DirectFundingConsumer.sol b/public/samples/VRF/v2-5/DirectFundingConsumer.sol new file mode 100644 index 00000000000..7a3f289ebb2 --- /dev/null +++ b/public/samples/VRF/v2-5/DirectFundingConsumer.sol @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: MIT +// An example of a consumer contract that directly pays for each request. +pragma solidity 0.8.19; + +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 {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. + */ + +/** + * Import IVRFV2PlusWrapper which is not yet available in the chainlink/contracts package. + * https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol + */ + +interface IVRFV2PlusWrapper { + /** + * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only + * be relied option within the same transaction that the request was made. + */ + function lastRequestId() external view returns (uint256); + + /** + * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + */ + function calculateRequestPrice( + uint32 _callbackGasLimit, + uint32 _numWords + ) external view returns (uint256); + + /** + * @notice Calculates the price of a VRF request in native with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + */ + function calculateRequestPriceNative( + uint32 _callbackGasLimit, + uint32 _numWords + ) external view returns (uint256); + + /** + * @notice Estimates the price of a VRF request with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPrice( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view returns (uint256); + + /** + * @notice Estimates the price of a VRF request in native with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPriceNative( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view returns (uint256); + + /** + * @notice Requests randomness from the VRF V2 wrapper, paying in native token. + * + * @param _callbackGasLimit is the gas limit for the request. + * @param _requestConfirmations number of request confirmations to wait before serving a request. + * @param _numWords is the number of words to request. + */ + function requestRandomWordsInNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes calldata extraArgs + ) external payable returns (uint256 requestId); + + function link() external view returns (address); + + function linkNativeFeed() external view returns (address); +} + +/** + * Import VRFV2PlusWrapperConsumerBase which is not yet available in the chainlink/contracts package. + * https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol + */ + +abstract contract VRFV2PlusWrapperConsumerBase { + error OnlyVRFWrapperCanFulfill(address have, address want); + + LinkTokenInterface internal immutable i_linkToken; + IVRFV2PlusWrapper public immutable i_vrfV2PlusWrapper; + + /** + * @param _vrfV2PlusWrapper is the address of the VRFV2Wrapper contract + */ + constructor(address _vrfV2PlusWrapper) { + IVRFV2PlusWrapper vrfV2PlusWrapper = IVRFV2PlusWrapper( + _vrfV2PlusWrapper + ); + + i_linkToken = LinkTokenInterface(vrfV2PlusWrapper.link()); + i_vrfV2PlusWrapper = vrfV2PlusWrapper; + } + + /** + * @dev Requests randomness from the VRF V2+ wrapper. + * + * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's + * fulfillRandomWords function. + * @param _requestConfirmations is the number of confirmations to wait before fulfilling the + * request. A higher number of confirmations increases security by reducing the likelihood + * that a chain re-org changes a published randomness outcome. + * @param _numWords is the number of random words to request. + * + * @return requestId is the VRF V2+ request ID of the newly created randomness request. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomness( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes memory extraArgs + ) internal returns (uint256 requestId, uint256 reqPrice) { + reqPrice = i_vrfV2PlusWrapper.calculateRequestPrice( + _callbackGasLimit, + _numWords + ); + i_linkToken.transferAndCall( + address(i_vrfV2PlusWrapper), + reqPrice, + abi.encode( + _callbackGasLimit, + _requestConfirmations, + _numWords, + extraArgs + ) + ); + return (i_vrfV2PlusWrapper.lastRequestId(), reqPrice); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomnessPayInNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes memory extraArgs + ) internal returns (uint256 requestId, uint256 requestPrice) { + requestPrice = i_vrfV2PlusWrapper.calculateRequestPriceNative( + _callbackGasLimit, + _numWords + ); + return ( + i_vrfV2PlusWrapper.requestRandomWordsInNative{value: requestPrice}( + _callbackGasLimit, + _requestConfirmations, + _numWords, + extraArgs + ), + requestPrice + ); + } + + /** + * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must + * @notice implement it. + * + * @param _requestId is the VRF V2 request ID. + * @param _randomWords is the randomness result. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords( + uint256 _requestId, + uint256[] memory _randomWords + ) internal virtual; + + function rawFulfillRandomWords( + uint256 _requestId, + uint256[] memory _randomWords + ) external { + address vrfWrapperAddr = address(i_vrfV2PlusWrapper); + if (msg.sender != vrfWrapperAddr) { + revert OnlyVRFWrapperCanFulfill(msg.sender, vrfWrapperAddr); + } + fulfillRandomWords(_requestId, _randomWords); + } + + /// @notice getBalance returns the native balance of the consumer contract + function getBalance() public view returns (uint256) { + return address(this).balance; + } + + /// @notice getLinkToken returns the link token contract + function getLinkToken() public view returns (LinkTokenInterface) { + return i_linkToken; + } +} + +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 callbackGasLimit = 100000; + + // 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 Arbitrum Sepolia + address linkAddress = 0xb1D4538B4571d411F07960EF2838Ce337FE1E80E; + + // address WRAPPER - hardcoded for Arbitrum Sepolia + address wrapperAddress = 0x29576aB8152A09b9DC634804e4aDE73dA1f3a3CC; + + constructor() + ConfirmedOwner(msg.sender) + VRFV2PlusWrapperConsumerBase(wrapperAddress) + {} + + function requestRandomWords() external onlyOwner returns (uint256) { + bytes memory extraArgs = VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ); + (uint256 requestId, uint256 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" + ); + } +} diff --git a/public/samples/VRF/v2-5/SubscriptionConsumer.sol b/public/samples/VRF/v2-5/SubscriptionConsumer.sol new file mode 100644 index 00000000000..e0a621a2dc4 --- /dev/null +++ b/public/samples/VRF/v2-5/SubscriptionConsumer.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +// An example of a consumer contract that relies on a subscription for funding. +pragma solidity 0.8.19; + +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"; + +/** + * 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 */ + IVRFCoordinatorV2Plus COORDINATOR; + + // Your subscription ID. + uint256 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-5/supported-networks + bytes32 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 callbackGasLimit = 100000; + + // 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_5.MAX_NUM_WORDS. + uint32 numWords = 2; + + /** + * HARDCODED FOR SEPOLIA + * COORDINATOR: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B + */ + constructor( + uint256 subscriptionId + ) VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) { + COORDINATOR = IVRFCoordinatorV2Plus( + 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B + ); + 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. + // To enable payment in native tokens, set nativePayment to true. + requestId = COORDINATOR.requestRandomWords( + VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: s_subscriptionId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ) + }) + ); + 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); + } +} diff --git a/public/samples/VRF/v2-5/SubscriptionManager.sol b/public/samples/VRF/v2-5/SubscriptionManager.sol new file mode 100644 index 00000000000..c8b8c54e8fe --- /dev/null +++ b/public/samples/VRF/v2-5/SubscriptionManager.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +// An example of a consumer contract that also owns and manages the subscription +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"; + +/** + * 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 VRFv2PlusSubscriptionManager is VRFConsumerBaseV2Plus { + LinkTokenInterface LINKTOKEN; + + // Sepolia coordinator. For other networks, + // see https://docs.chain.link/docs/vrf/v2-5/subscription-supported-networks#configurations + address vrfCoordinatorV2Plus = 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B; + + // 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/v2-5/subscription-supported-networks#configurations + bytes32 keyHash = + 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae; + + // A reasonable default is 100000, but this value could be different + // on other networks. + uint32 callbackGasLimit = 100000; + + // 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; + uint256 public s_subscriptionId; + + constructor() VRFConsumerBaseV2Plus(vrfCoordinatorV2Plus) { + s_vrfCoordinator = IVRFCoordinatorV2Plus(vrfCoordinatorV2Plus); + LINKTOKEN = LinkTokenInterface(link_token_contract); + //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 = s_vrfCoordinator.requestRandomWords( + VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: s_subscriptionId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ) + }) + ); + } + + 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 = s_vrfCoordinator.createSubscription(); + // Add this contract as a consumer of its own subscription. + s_vrfCoordinator.addConsumer(s_subscriptionId, address(this)); + } + + // Assumes this contract owns link. + // 1000000000000000000 = 1 LINK + function topUpSubscription(uint256 amount) external onlyOwner { + LINKTOKEN.transferAndCall( + address(s_vrfCoordinator), + amount, + abi.encode(s_subscriptionId) + ); + } + + function addConsumer(address consumerAddress) external onlyOwner { + // Add a consumer contract to the subscription. + s_vrfCoordinator.addConsumer(s_subscriptionId, consumerAddress); + } + + function removeConsumer(address consumerAddress) external onlyOwner { + // Remove a consumer contract from the subscription. + s_vrfCoordinator.removeConsumer(s_subscriptionId, consumerAddress); + } + + function cancelSubscription(address receivingWallet) external onlyOwner { + // Cancel the subscription and send the remaining LINK to a wallet address. + s_vrfCoordinator.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); + } +} diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts index 4297f90fd20..b5718e5d2e8 100644 --- a/src/config/sidebar.ts +++ b/src/config/sidebar.ts @@ -738,36 +738,58 @@ export const SIDEBAR: Partial> = { ], vrf: [ { - section: "Chainlink VRF", + section: "Chainlink VRF v2.5", contents: [ { - title: "Overview", + title: "V2.5 Overview", url: "vrf", + children: [ + { + title: "Subscription overview", + url: "vrf/v2-5/overview/subscription", + }, + { + title: "Direct funding overview", + url: "vrf/v2-5/overview/direct-funding", + }, + ], }, { - title: "Getting Started", - url: "vrf/v2/getting-started", + title: "Migration from V2", + url: "vrf/v2-5/migration-from-v2", + }, + { + title: "V2.5 Supported Networks", + url: "vrf/v2-5/supported-networks", }, { title: "Security Considerations", - url: "vrf/v2/security", + url: "vrf/v2-5/security", }, { title: "Best Practices", - url: "vrf/v2/best-practices", + url: "vrf/v2-5/best-practices", }, { - title: "Billing", - url: "vrf/v2/estimating-costs", + 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: "Subscription Method", + section: "V2 Subscription Method", contents: [ { title: "Introduction", @@ -800,7 +822,7 @@ export const SIDEBAR: Partial> = { ], }, { - section: "Direct Funding Method", + section: "V2 Direct Funding Method", contents: [ { title: "Introduction", diff --git a/src/content/vrf/index.mdx b/src/content/vrf/index.mdx index e3367d01e9f..606a2b227f0 100644 --- a/src/content/vrf/index.mdx +++ b/src/content/vrf/index.mdx @@ -4,22 +4,23 @@ date: Last Modified title: "Chainlink VRF" isMdx: true isIndex: true -whatsnext: { "Subscription Method": "/vrf/v2/subscription", "Direct Funding Method": "/vrf/v2/direct-funding" } +whatsnext: { "Subscription Method": "/vrf/v2-5/overview/subscription" } metadata: title: "Generate Random Numbers for Smart Contracts using Chainlink VRF" description: "Learn how to securely generate random numbers for your smart contract with Chainlink VRF (an RNG). This guide uses Solidity code examples." --- -import VrfCommon from "@features/vrf/v2/common/VrfCommon.astro" +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" import { Aside } from "@components" - + **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 ensures that results cannot be tampered with or manipulated by any single entity including oracle operators, miners, users, or smart contract developers. - + Use Chainlink VRF to build reliable smart contracts for any applications that rely on unpredictable outcomes: @@ -27,37 +28,41 @@ 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. -To learn more about the benefits of Chainlink VRF v2, see our blog post [Chainlink VRF v2 Is Now Live on Mainnet](https://blog.chain.link/vrf-v2-mainnet-launch/). 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). +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 -Chainlink VRF v2 offers two methods for requesting randomness: +Similarly to VRF v2, VRF v2.5 will offer two methods for requesting randomness: -- [Subscription](/vrf/v2/subscription): Create a subscription account and fund its balance with LINK tokens. Users 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/direct-funding): Consuming contracts directly pay with LINK when they request random values. You must directly fund your consumer contracts and ensure that there are enough LINK tokens to pay for randomness requests. +- [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: {/* prettier-ignore */} -| [Subscription method](/vrf/v2/subscription) | [Direct funding method](/vrf/v2/direct-funding) | +| [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/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/direct-funding). | +| 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 [Subscription supported networks](/vrf/v2/subscription/supported-networks/#configurations). | 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 [Direct funding supported networks](/vrf/v2/direct-funding/supported-networks/#configurations). | +| 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#configurations). | 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#configurations). | | 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. [Manage and monitor your balance](/vrf/v2/subscription/ui) | No refunds for overpayment after requests are completed | -| Flexible funding method first introduced in VRF v2. [Compare the VRF v2 subscription method to VRF v1](/vrf/v2/subscription/migration-from-v1). | Similar funding method to VRF v1, with the benefit of receiving more random values per request than VRF v1. [Compare direct funding in VRF v2 and v1](/vrf/v2/direct-funding/migration-from-v1). | +| 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 following pages: - -- [Subscription Supported networks](/vrf/v2/subscription/supported-networks) -- [Direct Funding Supported networks](/vrf/v2/direct-funding/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 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). +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). diff --git a/src/content/vrf/release-notes.mdx b/src/content/vrf/release-notes.mdx index 4dec6989b6a..17e004feac0 100644 --- a/src/content/vrf/release-notes.mdx +++ b/src/content/vrf/release-notes.mdx @@ -3,13 +3,22 @@ section: vrf date: Last Modified title: "Chainlink VRF Release Notes" isMdx: true -whatsnext: - { - "Get a Random Number (Direct funding)": "/vrf/v2/direct-funding/examples/get-a-random-number", - "Get a Random Number (Subscription)": "/vrf/v2/subscription/examples/get-a-random-number", - } +whatsnext: { "Migrate to VRF V2.5": "/vrf/v2-5/migration-from-v2" } --- +## 2024-04-29 - VRF V2.5 released on Ethereum, BNB Chain, Polygon, Avalanche and Arbitrum + +VRF V2.5 is available on Ethereum, BNB Chain, Polygon, Avalanche and Arbitrum mainnets and testnets. + +The new version of Chainlink VRF implements the following changes: + +- Support for native gas token billing +- Easy 1-click migration to future new versions +- New [billing model](/vrf/v2-5/billing), where the premium is a percentage of the gas costs of the VRF callback instead of a flat fee +- Gas optimizations + +Learn how to [migrate to VRF V2.5](/vrf/v2-5/migration-from-v2). + ## 2024-04-13 - Polygon testnet support changed The Mumbai network has stopped producing blocks, so example code will not function on this network. Check again soon diff --git a/src/content/vrf/v2-5/arbitrum-cost-estimation.mdx b/src/content/vrf/v2-5/arbitrum-cost-estimation.mdx new file mode 100644 index 00000000000..602b8851303 --- /dev/null +++ b/src/content/vrf/v2-5/arbitrum-cost-estimation.mdx @@ -0,0 +1,161 @@ +--- +section: vrf +date: Last Modified +title: "VRF Cost Estimation on Arbitrum" +metadata: + title: "Estimating costs for Chainlink VRF v2.5 on Arbitrum" + description: "Learn how to estimate costs for Chainlink VRF v2.5 on Arbitrum." +isMdx: true +--- + +import { Tabs, TabsContent } from "@components/Tabs" + +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 + +{/* prettier-ignore */} + +Subscription +Direct funding + +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 +``` + + + +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-cost-estimation). + +```typescript +// VRF variables and calculations +// --------------------------------- +// Full script: https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf/arbitrum-cost-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) +``` diff --git a/src/content/vrf/v2-5/best-practices.mdx b/src/content/vrf/v2-5/best-practices.mdx new file mode 100644 index 00000000000..f0e1142cf61 --- /dev/null +++ b/src/content/vrf/v2-5/best-practices.mdx @@ -0,0 +1,230 @@ +--- +section: vrf +date: Last Modified +title: "VRF Best Practices" +metadata: + title: "Chainlink VRF API Reference" + description: "Best practices for using Chainlink VRF." +--- + +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" +import { CodeSample } from "@components" + + + +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. + +{/* prettier-ignore */} +```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. + +{/* prettier-ignore */} +```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. + +{/* prettier-ignore */} +```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: + +{/* prettier-ignore */} +```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); + } +} +``` diff --git a/src/content/vrf/v2-5/billing.mdx b/src/content/vrf/v2-5/billing.mdx new file mode 100644 index 00000000000..73cffebd3ae --- /dev/null +++ b/src/content/vrf/v2-5/billing.mdx @@ -0,0 +1,355 @@ +--- +section: vrf +date: Last Modified +title: "VRF Billing" +metadata: + title: "Estimating costs for Chainlink VRF v2.5" + description: "Learn how to estimate costs for Chainlink VRF v2.5." +isMdx: true +--- + +import { CodeSample } from "@components" +import { TabsContent } from "@components/Tabs" + +This guide explains how to estimate VRF 2.5 costs for both the subscription and direct funding methods. + +## Understanding transaction costs + +{/* prettier-ignore */} + +Subscription +Direct funding + +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. + + + + +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 + +{/* prettier-ignore */} + +Subscription +Direct funding + +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 +``` + +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#configurations) for your selected network. + + + +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#configurations) 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 + +{/* prettier-ignore */} + +Subscription +Direct funding + +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/#configurations). 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. + + + +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#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-5/supported-networks#configurations) 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. +{/* prettier-ignore */} + + +Paying in LINK +Paying in ETH + +| 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) | + +1. 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 | + +1. 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. + + + +| 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) | + +1. 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 +Paying in ETH + +| 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) | + +1. 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 | + +1. 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. + + + +| 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) | + +1. 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 +Paying in ETH + +| 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) | + +1. 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 | + +1. 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. + + + +| 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) | + +1. 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. + + + diff --git a/src/content/vrf/v2-5/migration-from-v2.mdx b/src/content/vrf/v2-5/migration-from-v2.mdx new file mode 100644 index 00000000000..8598fdc9c5a --- /dev/null +++ b/src/content/vrf/v2-5/migration-from-v2.mdx @@ -0,0 +1,530 @@ +--- +section: vrf +date: Last Modified +title: "Migrating from VRF v2" +--- + +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" +import { Aside, CodeSample } from "@components" +import { Tabs, TabsContent } from "@components/Tabs" + + + +## 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: + +{/* prettier-ignore */} + +Subscription +Direct funding + +The `requestRandomWords` function now uses `VRFV2PlusClient.RandomWordsRequest` with a mapping labeling each part of the request: + +{/* 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})) + }) +); +``` + +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. + + + +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. + +{/* prettier-ignore */} +```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 on all [supported networks](/vrf/v2-5/supported-networks) and direct funding on Arbitrum Sepolia. 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, which directly includes the latest V2.5 wrapper and interface: + + + +### Update your code + +To modify your existing smart contract code to work with VRF v2.5, complete the following changes: + +{/* prettier-ignore */} + +Subscription +Direct funding + +1. Import the [`VRFConsumerBaseV2Plus`](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol) contract and remove the v2 `VRFConsumerBaseV2` import. + +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), and update any old references to the VRF V2 coordinator in your contract. + +1. Add a `VRFConsumerBaseV2Plus` constructor, passing in the LINK token address for the network you're using. + +1. 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` mapping, and specify whether or not you want to pay for VRF requests using native tokens: + + {/* prettier-ignore */} + + LINK + Native tokens + + + {/* 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})) + }) + ); + ``` + + + + + {/* 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})) + }) + ); + ``` + + + + + + + + +1. Import the [`VRFV2PlusWrapperConsumerBase`](https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol) contract and remove the v2 `VRFV2WrapperConsumerBase` import. + +1. Add a `VRFV2PlusWrapperConsumerBase` constructor, passing in the VRF wrapper address for the network you're using. Unlike V2, you don't have to pass the LINK token address to the constructor. + +1. You can still call the `requestRandomness` function. However, the V2.5 `requestRandomness` function requires one additional parameter, `extraArgs`. Use `nativePayment` to specify whether or not you want to pay for VRF requests using native tokens: + + {/* prettier-ignore */} + + LINK + Native tokens + + + {/* prettier-ignore */} + ```solidity + bytes memory extraArgs = VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ); + (uint256 reqId, uint256 reqPrice) = requestRandomness( + callbackGasLimit, + requestConfirmations, + numWords, + extraArgs + ); + ``` + + + + + + {/* prettier-ignore */} + ```solidity + bytes memory extraArgs = VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: true}) + ); + (uint256 reqId, uint256 reqPrice) = requestRandomness( + callbackGasLimit, + requestConfirmations, + numWords, + extraArgs + ); + ``` + + + + + +1. The V2.5 `requestRandomness` function returns a tuple: `(uint256 requestId, uint256 requestPrice)`. Adjust your `requestRandomWords` function or any other functions in your code where you call `requestRandomness`. + +1. Make sure your contract has a withdraw function for both native tokens and LINK. Refer to the `withdrawLink` and `withdrawNative` functions in the [`VRFV2PlusWrapperConsumerExample`](https://github.com/smartcontractkit/chainlink/blob/develop/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: + + + +Compare the major changes between V2.5 and V2: + +{/* prettier-ignore */} + +VRF V2.5 example code +VRF V2 example code + + +{/* prettier-ignore */} +```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 {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. + \*/ + +///// INHERIT NEW CONSUMER BASE CONTRACT ///// +contract SubscriptionConsumer is VRFConsumerBaseV2Plus { +... + + ///// USE NEW COORDINATOR ///// + IVRFCoordinatorV2Plus COORDINATOR; + + ///// 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 AND COORDINATOR CONSTRUCTORS ///// + constructor( + ///// UPDATE TO UINT256 ///// + uint256 subscriptionId + ) + VRFConsumerBaseV2Plus(0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B) + { + COORDINATOR = IVRFCoordinatorV2Plus( + 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. + requestId = COORDINATOR.requestRandomWords( + VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: s_subscriptionId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ) + }) + ); + ... + } + ... + +} +``` + + + + +{/* prettier-ignore */} +```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: + + + + + +Compare the major changes between V2.5 and V2: + +{/* prettier-ignore */} + +VRF V2.5 example code +VRF V2 example code + + +{/* prettier-ignore */} +```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() + external + onlyOwner + returns (uint256) + { + ///// UPDATE TO NEW V2.5 REQUEST FORMAT: ADD EXTRA ARGS ///// + bytes memory extraArgs = VRFV2PlusClient._argsToBytes( + VRFV2PlusClient.ExtraArgsV1({nativePayment: false}) + ); + + ///// REQUESTRANDOMNESS RETURNS A TUPLE ///// + (uint256 reqId, uint256 reqPrice) = requestRandomness( + callbackGasLimit, + requestConfirmations, + numWords, + extraArgs ///// PASS IN EXTRA ARGS ///// + ); + + ... + return reqId; + } + ... +} +``` + + + + +{/* prettier-ignore */} +```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; + } + +... + +} +``` + + + diff --git a/src/content/vrf/v2-5/overview/direct-funding.mdx b/src/content/vrf/v2-5/overview/direct-funding.mdx new file mode 100644 index 00000000000..4cf5cbd700b --- /dev/null +++ b/src/content/vrf/v2-5/overview/direct-funding.mdx @@ -0,0 +1,81 @@ +--- +section: vrf +date: Last Modified +title: "Direct Funding Method" +isIndex: true +whatsnext: + { + "Get a Random Number": "/vrf/v2/direct-funding/examples/get-a-random-number", + "Supported Networks": "/vrf/v2/direct-funding/supported-networks", + } +metadata: + title: "Generate Random Numbers for Smart Contracts using Chainlink VRF v2.5 - Direct funding method" + description: "Learn how to securely generate random numbers for your smart contract with Chainlink VRF v2.5. This guide uses the Direct funding method." +--- + +import VrfCommon from "@features/vrf/v2/common/VrfCommon.astro" +import { Aside, ClickToZoom } from "@components" + +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. + + + +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](/vrf/v2/direct-funding#request-and-receive-data) similarly to VRF V2. + +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.5 solution uses both offchain and onchain components: + +- [VRF v2.5 Wrapper (onchain component)](https://github.com/smartcontractkit/chainlink/blob/master/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/master/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. + +### Set up your contract and request + +Set up your consuming contract: + +1. Your contract must inherit [VRFV2PlusWrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol). + +1. 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. + +1. Submit your VRF request by calling the `requestRandomness` function in the [VRFV2PlusWrapperConsumerBase](https://github.com/smartcontractkit/chainlink/blob/develop/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#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-5/supported-networks#configurations) 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/develop/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). + +1. The consuming contract calls the [LinkToken](https://github.com/smartcontractkit/chainlink/blob/develop/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/master/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol) `onTokenTransfer` logic. + +1. The VRFV2PlusWrapper's `onTokenTransfer` logic triggers the [VRF 2.5 Coordinator](https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol) `requestRandomWords` function to request randomness. + +1. The VRF coordinator emits an event. + +1. 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`). + +1. The VRF coordinator verifies the proof onchain, then it calls back the wrapper contract's `fulfillRandomWords` function. + +1. 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.5 Wrapper adds an overhead, your `callbackGasLimit` must not exceed `maxGasLimit - wrapperGasOverhead`. Learn more about [estimating costs](/vrf/v2/estimating-costs). diff --git a/src/content/vrf/v2-5/overview/subscription.mdx b/src/content/vrf/v2-5/overview/subscription.mdx new file mode 100644 index 00000000000..9cf8d0a5dc3 --- /dev/null +++ b/src/content/vrf/v2-5/overview/subscription.mdx @@ -0,0 +1,177 @@ +--- +section: vrf +date: Last Modified +title: "Subscription Method" +isIndex: true +metadata: + title: "Generate Random Numbers for Smart Contracts using Chainlink VRF v2.5 - Subscription Method" + description: "Learn how to securely generate random numbers for your smart contract with Chainlink VRF v2.5(an RNG). This guide uses the subscription method." +--- + +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" +import { Aside, ClickToZoom } from "@components" +import { TabsContent } from "@components/Tabs" +import { YouTube } from "@astro-community/astro-embed-youtube" + + + +This section explains how to generate random numbers using the subscription method. + + + +## 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 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](/vrf/v2/subscription#request-and-receive-data) similarly to VRF V2. + + + +VRF v2.5 uses both offchain and onchain components: + +- [VRF v2.5 Coordinator (onchain component)](https://github.com/smartcontractkit/chainlink/blob/master/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. + +### Set up your contract and request + +Set up your consuming contract: + +1. Your contract must inherit [VRFConsumerBaseV2Plus](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol). + +1. 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. + +1. Submit your VRF request by calling `requestRandomWords` of the [VRF Coordinator](https://github.com/smartcontractkit/chainlink/blob/develop/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#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-5/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-5/supported-networks#configurations). + +In VRF 2.5, the request format has changed: + +{/* prettier-ignore */} + +```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. + +1. 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`). + +1. 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 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 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. + +{/* prettier-ignore */} + +LINK +Native tokens + +``` +(((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) +``` + + + +``` +(((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. diff --git a/src/content/vrf/v2-5/security.mdx b/src/content/vrf/v2-5/security.mdx new file mode 100644 index 00000000000..60cfa47b965 --- /dev/null +++ b/src/content/vrf/v2-5/security.mdx @@ -0,0 +1,56 @@ +--- +section: vrf +date: Last Modified +title: "VRF Security Considerations" +--- + +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 `VRFConsumerBaseV2Plus` in your contract to interact with the VRF service](#use-vrfconsumerbasev2plus-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 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. +1. **Stop accepting further user actions that might affect the generated NFT** and issue a randomness request. +1. 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`. diff --git a/src/content/vrf/v2-5/subscription/create-manage.mdx b/src/content/vrf/v2-5/subscription/create-manage.mdx new file mode 100644 index 00000000000..fc439f7ad59 --- /dev/null +++ b/src/content/vrf/v2-5/subscription/create-manage.mdx @@ -0,0 +1,86 @@ +--- +section: vrf +date: Last Modified +title: "Create and manage VRF V2.5 subscriptions" +--- + +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" +import { CodeSample } from "@components" +import { Tabs, TabsContent } from "@components/Tabs" + + + +## Using the VRF Subscription Manager + +The private version of the VRF Subscription Manager is available to help you create and manage VRF V2.5 subscriptions. 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. + +1. 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. + +1. Your new subscription shows in the **My Subscriptions** list, along with 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**. + +1. 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**. + +1. 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. + +1. 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. + +## 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: + + {/* prettier-ignore */} + + Subscription contract + Using a block explorer + + Deploy the [`SubscriptionManager` contract](/samples/VRF/v2-5/SubscriptionManager.sol). On deployment, the contract creates a new subscription and adds itself as a consumer to the new subscription. + + + 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. + 1. In the **Contract** tab, select the **Write contract** tab. Connect your wallet to the block explorer. + 1. Expand the `createSubscription` function and select the **Write** button. Follow the prompts in MetaMask to confirm the transaction. + 1. Get your subscription ID for the next step, funding your subscription. + + + +1. Fund your new VRF v2.5 subscription: + + {/* prettier-ignore */} + + Subscription contract + Using a block explorer + + 1. [Fund your new `VRFv2PlusSubscriptionManager` contract](/resources/fund-your-contract). + 1. Call `topUpSubscription` from the `VRFv2PlusSubscriptionManager` contract. This function uses the LINK token contract's `transferAndCall` function to fund your new subscription. + + + 1. [Fund your new `VRFv2PlusSubscriptionManager` contract](/resources/fund-your-contract). + 1. 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. + 1. In the **Contract** tab, select the **Write contract** tab. Connect your wallet to the block explorer. + 1. 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. + 1. Select the **Write** button and follow the prompts in MetaMask to confirm the transaction. + + diff --git a/src/content/vrf/v2-5/supported-networks.mdx b/src/content/vrf/v2-5/supported-networks.mdx new file mode 100644 index 00000000000..609187552e1 --- /dev/null +++ b/src/content/vrf/v2-5/supported-networks.mdx @@ -0,0 +1,467 @@ +--- +section: vrf +date: Last Modified +title: "Supported Networks" +metadata: + title: "Chainlink VRF v2.5 Supported Networks" + linkToWallet: true + image: "/files/OpenGraph_V3.png" +--- + +import VrfCommon from "@features/vrf/v2-5/VrfCommon.astro" +import ResourcesCallout from "@features/resources/callouts/ResourcesCallout.astro" +import { Address, Aside, CopyText } from "@components" +import { TabsContent } from "@components/Tabs" + + + +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. + +## Configurations + + + +VRF v2.5 coordinators for subscription funding are available on several networks. + + + +### Ethereum mainnet + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 30 gwei Key Hash | | +| 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 | + + + +### Sepolia testnet + + + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 30 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 30 gwei Key Hash | | +| 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 | + + + +### BNB Chain + + + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | +| 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 + +{/* prettier-ignore */} + +Subscription +Direct funding + + + +| Item | Value | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| LINK Token |
| +| VRF Coordinator |
| +| 50 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 50 gwei Key Hash | | | +| 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 | + + + +### Polygon (Matic) mainnet + + + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | +| Premium percentage
(paying with MATIC) | 84 | +| Premium percentage
(paying with LINK) | 70 | +| Max Gas Limit | 2,500,000 | +| Minimum Confirmations | 3 | +| Maximum Confirmations | 200 | +| Maximum Random Values | 500 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | | +| Premium percentage
(paying with MATIC) | 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 + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 500 gwei Key Hash | | +| Premium percentage
(paying with testnet MATIC) | 84 | +| Premium percentage
(paying with testnet LINK) | 70 | +| Max Gas Limit | 2,500,000 | +| Minimum Confirmations | 3 | +| Maximum Confirmations | 200 | +| Maximum Random Values | 500 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 500 gwei Key Hash | | | +| Premium percentage
(paying with testnet MATIC) | 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 | + + + +### Avalanche mainnet + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 200 gwei Key Hash | | +| 500 gwei Key Hash | | +| 1000 gwei Key Hash | | | +| 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 + + + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| | +| VRF Coordinator |
| +| 300 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 300 gwei Key Hash | | | +| 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 | + + + +### Arbitrum mainnet + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| | +| VRF Coordinator |
| +| 2 gwei Key Hash | | +| 30 gwei Key Hash | | +| 150 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 2 gwei Key Hash | | +| 30 gwei Key Hash | | +| 150 gwei Key Hash | | | +| 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 + + + +{/* prettier-ignore */} + +Subscription +Direct funding + +| Item | Value | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| | +| VRF Coordinator |
| +| 50 gwei Key Hash | | +| 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 | + + +| Item | Value | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| LINK Token |
| +| VRF Wrapper |
| +| VRF Coordinator |
| +| 50 gwei Key Hash | | | +| 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 | + + diff --git a/src/content/vrf/v2/estimating-costs.mdx b/src/content/vrf/v2/estimating-costs.mdx index b7f88f2e01c..0cdd84a79ce 100644 --- a/src/content/vrf/v2/estimating-costs.mdx +++ b/src/content/vrf/v2/estimating-costs.mdx @@ -368,12 +368,12 @@ This conversion allows us to estimate the L1 callback gas cost and incorporate i 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). +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-cost-estimation). ```typescript // VRF variables and calculations // --------------------------------- -// Full script: https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf-arbitrum-gas-estimation +// Full script: https://github.com/smartcontractkit/smart-contract-examples/tree/main/vrf/arbitrum-cost-estimation // --------------------------------- // Estimated upper bound of verification gas for VRF subscription. // To see an estimate with an average amount of verification gas, diff --git a/src/content/vrf/v2/security.mdx b/src/content/vrf/v2/security.mdx index 2d25f4944a4..c3c4d0aa01b 100644 --- a/src/content/vrf/v2/security.mdx +++ b/src/content/vrf/v2/security.mdx @@ -59,4 +59,4 @@ If you implement the [subscription method](/vrf/v2/subscription), use `VRFConsum ## 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`. +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`. \ No newline at end of file diff --git a/src/features/vrf/v2-5/VrfCommon.astro b/src/features/vrf/v2-5/VrfCommon.astro new file mode 100644 index 00000000000..c48e0b141a1 --- /dev/null +++ b/src/features/vrf/v2-5/VrfCommon.astro @@ -0,0 +1,15 @@ +--- +const availability = await Astro.glob("./availability.mdx") +const AvailabilityComponent = availability[0].Content + +const security = await Astro.glob("./security.mdx") +const SecurityComponent = security[0].Content + +export type Props = { + callout?: "availability" | "security" +} +const { callout } = Astro.props as Props +--- + +{callout === "availability" && } +{callout === "security" && } diff --git a/src/features/vrf/v2-5/availability.mdx b/src/features/vrf/v2-5/availability.mdx new file mode 100644 index 00000000000..19bb10f22a0 --- /dev/null +++ b/src/features/vrf/v2-5/availability.mdx @@ -0,0 +1,6 @@ +import { Aside } from "@components" + + diff --git a/src/features/vrf/v2-5/security.mdx b/src/features/vrf/v2-5/security.mdx new file mode 100644 index 00000000000..ebb80a1e97e --- /dev/null +++ b/src/features/vrf/v2-5/security.mdx @@ -0,0 +1,5 @@ +import { Aside } from "@components" + + \ No newline at end of file