Chainlink VRF Security Considerations
3 sept 2024
8 Minutes
Generating true randomness on a blockchain is a challenging problem due to the inherently deterministic nature of distributed ledger technology. In traditional computing environments, randomness can be generated by using unpredictable inputs, such as mouse movements, CPU temperature, or atmospheric noise. However, blockchain environments lack such unpredictable external sources of entropy. Blockchain randomness generation is impossible for several reasons, as we will see below.
Table of Contents
Deterministic Nature of Blockchains
Manipulation Risks
Consensus-Based Randomness Issues
Chainlink VRF: All you need to know
Security Considerations
Conclusion
1. Deterministic Nature of Blockchains:
Consensus Mechanism: Blockchains rely on consensus mechanisms (e.g., Proof of Work, Proof of Stake) to ensure that all participants (nodes) in the network agree on the state of the ledger. For all nodes to reach the same state, every transaction, including smart contract execution, must produce the same result for everyone. This deterministic behavior is crucial for the integrity of the blockchain, but it also means that any random number generated by a smart contract must be the same across all nodes.
Predictability: Because the blockchain's execution is deterministic, any method used to generate randomness using blockchain data (like block hashes, timestamps, or account balances) can potentially be predicted by someone with enough computational resources or information about the system. For example, if a block hash is used to generate randomness, miners could manipulate the hash by controlling the block's contents, thereby influencing the random outcome.
2. Manipulation Risks:
Miner Influence: In Proof of Work blockchains, miners have the power to influence the content of a block, including the block's hash. If a random number is derived from this hash, a miner could attempt to manipulate the block contents until a favorable random number is produced, thereby undermining the fairness of the randomness.
Front-Running: On blockchains like Ethereum, where transactions are public before being included in a block, an attacker could observe a randomness-dependent transaction and submit their own transaction to influence or exploit the outcome before the original transaction is mined.
3. Consensus-Based Randomness Issues:
Coordinated Attacks: In some systems, randomness might be generated by aggregating contributions from multiple participants (e.g., multi-party computation). However, if some of the participants are colluding or compromised, they could potentially influence the final outcome.
Therefore, any protocol that uses predictable sources to generate randomness for performing any kind of operation within the protocol will lead to several problems and be considered insecure due to the deterministic nature of blockchain technology. However, an innovative and widely used solution has been developed by Chainlink, the Chainlink VRF.
Chainlink VRF: All you need to know
Chainlink VRF (Verifiable Random Function) is a service provided by Chainlink, a decentralized oracle network, that allows smart contracts to generate provably fair and verifiable random numbers. This service is crucial for applications such as gaming, lotteries, and other use cases where randomness and fairness are essential.
Key Features of Chainlink VRF:
Provably Fair: Chainlink VRF ensures that the randomness generated is not only random but also verifiable. This means that anyone can confirm that the random number was generated fairly and was not tampered with by any party, including the oracle providing the randomness.
Tamper-Proof: Since the randomness is generated using a combination of block data and a pre-committed secret key by the Chainlink node, it cannot be predicted or manipulated by anyone, including the node operators themselves.
Verifiable: After generating the random number, Chainlink VRF provides cryptographic proof that the process was executed correctly. This proof is published on-chain, where it can be independently verified by any observer or smart contract.
Secure and Decentralized: Chainlink VRF is powered by Chainlink's decentralized oracle network, which enhances security by reducing the risk of any single point of failure or attack.
Chainlink VRF operates through the following steps:
Request Initiation: A smart contract on the blockchain requests a random number by submitting a 'VRF request' to the Chainlink VRF service.
Oracle Selection: The Chainlink network picks a set of trusted oracles to process the request. These oracles are chosen for their track record in delivering accurate and secure random numbers.
Random Number Creation: The selected oracles each generate random numbers independently, which are then combined into a single verifiable random result.
Cryptographic Proof: Along with the random number, the oracles provide a cryptographic proof that can be validated on the blockchain, ensuring the number was generated securely and without interference.
On-Chain Verification: The smart contract checks this proof to ensure the random number is authentic and has not been tampered with.
Security Considerations
As with everything in blockchain, the development of smart contracts involves inherent risks, and the implementation of Chainlink VRF is no exception. To ensure the security and reliability of the system, it is crucial to mitigate these risks through careful planning and considering some security risk avoidance points.
Use requestID to ensure that randomness requests and their corresponding fulfillments are correctly matched
If your contract is capable of making multiple VRF requests at the same time, it’s crucial to prevent any manipulation of the sequence in which these fulfillments are processed, as this could affect critical operations related to your users.
Blockchain miners and validators have the ability to control the order in which your requests are processed, which in turn influences how your contract handles these requests.
For example, if you submit randomness requests A, B, and C in rapid succession, there’s no guarantee that the fulfillments will arrive in the same sequence. They could arrive in any order, such as C, A, B, or another combination.
To address this issue and ensure that each randomness request is correctly linked to its fulfillment, it’s highly recommended to use requestIds. This approach not only promotes consistency but also strengthens the security and reliability of your contract’s operations.
Avoid Re-Requesting Randomness
Re-requesting randomness using VRFv2 is considered an inappropriate practice. Doing so could enable the VRF service provider to withhold the initial VRF fulfillment if the result isn’t to their advantage. They might then wait for the re-request, hoping to produce a more favorable outcome, similar to the concerns related to block confirmation times.
Since re-requesting randomness is easily detectable on the blockchain, it’s important to avoid this practice, especially in scenarios where proper use of VRFv2 is critical.
Select a Safe Block Confirmation Time, Which Varies Across Blockchains
In theory, miners or validators on a blockchain have the ability to alter the blockchain’s history, which could involve placing a randomness request from your contract into a different block. This would result in a different VRF output. While this doesn’t allow a miner to predict the random value in advance, it does give them the opportunity to generate a new random value, which might or might not work in their favor. Essentially, they can only reset the randomness, similar to rerolling dice, without knowing the outcome beforehand.
To protect your application and mitigate the risk of potential rewrite attacks, it’s essential to choose an appropriate confirmation time for your randomness requests. The confirmation time refers to the number of blocks the VRF service waits before finalizing a fulfillment on the blockchain. This delay is designed to reduce the profitability of any potential rewrite attacks in the context of your application.
Do Not Accept Bids/Bets/Inputs After Making a Randomness Request
Consider a contract that generates a random NFT based on user interactions. In this case, the contract should:
Record User Actions: Document any user actions that could influence the NFT being created.
Stop Accepting Inputs: Cease accepting any further user interactions that might affect the NFT.
Request Randomness: Initiate a randomness request.
Mint the NFT: Proceed with minting the NFT once the randomness fulfillment is received.
More broadly, if your contract’s outcome depends on a combination of user inputs and randomness, it’s crucial that the contract stops accepting additional user inputs after the randomness request has been made. Allowing further inputs could compromise the cryptoeconomic security of the contract, as an attacker might exploit the opportunity to alter the blockchain’s history to their advantage.
Ensure that the fulfillRandomWords Function Does Not Revert
If your fulfillRandomWords() function encounters an error and reverts, the VRF service will not retry the call. To maintain smooth operation, it's crucial that this function does not cause a revert. A practical strategy is to securely store the randomness and handle any complex subsequent actions through separate contract calls. These calls can be initiated by you, your users, or an Automation Node, ensuring that the process remains reliable and consistent.
Use VRFConsumerBaseV2 in Your Contract to Interact with the VRF Service
When implementing the subscription method, it is advisable to use the VRFConsumerBaseV2 contract. This base contract includes a validation mechanism to confirm that randomness is fulfilled by VRFCoordinatorV2. For optimal implementation, inherit from VRFConsumerBaseV2. Additionally, avoid overriding the rawFulfillRandomness function, as it is crucial for the proper functioning of your contract.
Conclusion
In summary, generating randomness on a blockchain is challenging due to its deterministic nature and susceptibility to manipulation. Chainlink's Verifiable Random Function (VRF) provides a secure solution by generating provably fair and tamper-proof random numbers using blockchain data and secret keys, accompanied by cryptographic proofs for verification.
To maintain security, developers should follow best practices such as using requestIds, avoiding re-requesting randomness, setting appropriate block confirmation times, and ensuring that critical functions do not revert. For more details, refer to the official Chainlink VRF v2 documentation.