VRF v2 billing model vs. v1 billing model
Hello,
I have concerns with one aspect of the Chainlink VRF v2 service – the billing method. As you know, Chainlink VRF v1 was deprecated earlier this year in favor of v2, with the VRF documentation stating that v2 is both a replacement and enhancement of v1. I agree that functionally, the v2 API is more powerful with the ability to specify a variable number of confirmations and execute more gas-intensive callback functions (among other things); however, the billing method has now become more unpredictable, due to several factors – (1) the amount of LINK that needs to be transferred to the VRF coordinator is based on a volatile exchange rate between ETH and LINK, which has shifted by orders of magnitude in the past, and (2) there seems to be a possibility that the ETH-LINK data feed used in the billing calculation may not be available (according to the VRF documentation), in which case a fallback conversion is used. (There is also the point that gas price themselves vary, but because the maximum gas price is limited by the VRF gas lane, this variable can be considered bounded.) This stands in contrast with the way billing was handled in VRF v1, where a flat LINK fee was all that was needed to get a random number. I think it is therefore misleading to say that v2 is an enhancement of v1, because developers now have the added burden of ensuring that the subscription balance for their protocol has enough LINK tokens, while previously in v1 developers could say with certainty whether an amount of LINK deposited by a user was enough to pay for randomness.
Broadly speaking, there seem to be two ways developers can fund VRF v2 transactions – they can either (1) monitor their LINK balance and replenish it whenever it runs low, or (2) request LINK directly from users and integrate this payment into the protocol/UX. The first option, in my view, goes against what decentralization is all about; the developer becomes something like a stagehand, keeping the show rolling by ensuring that the subscription is sufficiently funded – otherwise callbacks can revert, potentially putting contracts in an inconsistent state. Even if the developer has the best of intentions, what if they are not there to refill the balance for some reason? What if they go bankrupt and cannot fund the balance any longer? The developer now becomes a single point of failure in the system.
For a personal project of mine, I prefer the second option of allowing users to fund their own VRF experience, and I believe developers should have the flexibility of programmatically requesting VRF fees from users in a reliable way if they do not want to monitor balances themselves. In other words, as long as I know that my code is unit-tested, I can sleep at night knowing users will always provide as much LINK as they need.
The problem I am facing with v2 is that it is not possible to guarantee that the amount of LINK a user provides to pay for VRF in the future will be enough. (Or, at least, I do not know of any totally reliable solution.) Suppose that a user wishes to deposit LINK into a contract, which in turn triggers some logic to generate a random number at a future time. The v1 solution was simple – the user pays a known LINK fee (0.0001 LINK on Polygon Mainnet, for example) – and at the desired time, the contract requests randomness. Such logic is no longer possible when using v2 – the user has to deposit some amount of LINK, but in the future, how does he/she know that this will be enough? The ETH-LINK exchange rate could have moved to a different value by then, so a callback that requires 200,000 gas may now be converted to an amount of LINK significantly greater than what the user had put in.
Developers with this kind of contract logic cannot follow the instructions in the VRF documentation to migrate from v1 to v2 because it would pose a fundamental change in billing, and thus a change in the way users interact with the protocol – what initially worked with certainty now requires a good deal of risk management and a modification of logic beyond just renaming a few functions. Step 1 tells developers to set up and fund a new subscription, but what if users were paying for randomness, not developers?
As it happens, I want to execute this type of logic in my own project, but found using v2 to be a dealbreaker for the reason I have described above. If v2 does not provide the same level of determinism as v1 for requesting LINK fees from users, I do not see how v2 can be called a replacement.
Thank you for raising this issue. We are actively discussing ways to mitigate these changes without removing the added flexibility and functionality that V2 brings. This includes considering how to continue the possibility of passing costs to end users, as you mentioned.
As you pointed out, V2 is not a drop-in replacement for V1. As a new version, it brings a degree of backward incompatibility due to some of the changes it contains. VRF v1's flat fee is unsustainable given the fulfillment costs are ultimately variable in nature
Again, thank you for raising this issue. More to follow.
Thanks for the reply. What do you mean by VRF v1's flat fee being unsustainable? My understanding was that the v1 fees were meant to cover the highest gas prices. Do you mean that, currently, a flat fee is unsustainable in the context of v2?
The cost of fulfilling the request depends on:
- gas used by the callback
- gas price at the time of fulfillment
- LINK/ETH price
Since each of the above parameters can have quite a wide range, V1 ends up not charging an accurate cost in the long run, it could be too high or too low.
The new direct funding model, V2, charges the user during the request, so the cost is known at the request time. However, the price it charges is dynamic and can be obtained programmatically at request time. This leads to a more sustainable model.