Randomness in Solidity

Kaan Kaçar
Coinmonks

--

In the world of decentralized applications, achieving randomness is a crucial aspect for various use cases like gaming, lotteries, and cryptographic operations. However, generating truly random numbers in a deterministic and transparent manner poses unique challenges. In this post, I will explore different techniques and best practices to achieve randomness in Solidity.

Pseudorandomness vs. True Randomness

Before diving into the techniques for achieving randomness, it’s important to understand the distinction between pseudorandomness and true randomness. Pseudorandom numbers are generated using deterministic algorithms, starting from a seed value. Given the same seed, the sequence of numbers generated will be the same every time. On the other hand, true randomness relies on unpredictable and unbiased sources of entropy, ensuring that the generated numbers are truly random and independent of any previous states.

Challenges in Achieving Randomness

Solidity is a deterministic programming language, meaning that the execution of a smart contract should always produce the same output given the same input. Achieving randomness within this deterministic environment is challenging due to the lack of access to external data, the inability to rely on timestamps, and the need for transparency and auditability.

Generating Randomness with Blockhash

One of the simplest ways to introduce randomness in Solidity is by utilizing the blockhash function. The blockhash function returns the hash of a specific block in Ethereum. However, there are limitations to its usage. It can only access the hash of the most recent 256 blocks. Moreover, miners can manipulate the block's timestamp within a certain range, potentially affecting the generated random number. Therefore, relying solely on blockhash for critical applications is not recommended.

To generate a random number using blockhash, you can implement a function like this:

function generateRandomNumber(uint256 seed) public view returns (uint256) {
uint256 blockNumber = block.number - 1; // Use the previous block's hash
bytes32 blockHash = blockhash(blockNumber);
return uint256(blockHash) % seed;
}

Utilizing Chainlink VRF (Verifiable Random Function)

To overcome the limitations of blockhash, external oracle services can be leveraged to achieve true randomness. Chainlink VRF is a widely used solution that provides provably random numbers generated by oracles.

Integrating Chainlink VRF into your smart contract involves the following steps:

  1. Import the Chainlink VRF Solidity library into your smart contract. Ensure you have the necessary contract interfaces and contract variables in place.
  2. Request Randomness: Invoke the requestRandomness function provided by Chainlink VRF to request a random number. This function requires an amount of LINK tokens as payment for the oracle service. It also takes in a seed value and a callback function that will be called when the randomness response is received.
  3. Receive Randomness: The callback function specified in the request is triggered when the randomness response is received. This function should handle the received randomness value appropriately within your application logic.
  4. Verify Randomness: To ensure the randomness generated by Chainlink VRF is legitimate, include a verification step. Chainlink provides a fulfillRandomness function that verifies the authenticity of the received random number by comparing it with the seed value.

For more: https://docs.chain.link/getting-started/intermediates-tutorial

Randomness from External Oracle

Apart from Chainlink VRF, other external oracle services can also be used to achieve randomness. These services provide APIs or smart contract interfaces that expose random number generation capabilities.

Commit-Reveal Schemes

Commit-reveal schemes are another approach to achieving randomness in Solidity. The process involves two phases: commitment and revelation.

In the commitment phase, participants submit hashed versions of their random choices. They keep the original random numbers secret until the revelation phase. The commitment can be achieved using the keccak256 hashing algorithm.

function commit(uint256 randomNumber) public {
bytes32 commitment = keccak256(abi.encodePacked(randomNumber));
// Store the commitment for later verification
// ...
}

In the revelation phase, participants reveal their original random numbers, which are then combined or processed to derive the final random output. The participants can submit their revealed values using a reveal function:

function reveal(uint256 randomNumber) public {
// Retrieve the commitment and verify the revealed value
bytes32 commitment = getCommitment(msg.sender);
require(keccak256(abi.encodePacked(randomNumber)) == commitment, "Invalid commitment");
// Process the revealed numbers to derive the final random output
// ...
}

Commit-reveal schemes provide fairness and prevent participants from influencing the outcome based on revealed values. However, the scheme’s effectiveness depends on the coordination and behavior of participants.

Randomness from External Contracts

Another method to achieve randomness involves utilizing external contracts specifically designed for generating random numbers. These contracts leverage various techniques like oracles, cryptographic operations, and external verifiable data sources to generate random numbers.

For example: https://github.com/axiomzen/eth-random or https://fravoll.github.io/solidity-patterns/randomness.html

Final Words

In this guide, I explored different techniques to achieve randomness, including utilizing blockhash, integrating Chainlink VRF, relying on external oracles, implementing commit-reveal schemes, and interfacing with external contracts. Each technique has its own advantages and considerations, so it's important to choose the approach that best fits your specific use case while considering factors like security, reliability, transparency, and decentralization.

Remember, achieving randomness in a deterministic environment is a complex task, and continuous research, testing, and auditing are necessary. It’s a lot of work. So maybe you should reconsider your gambling game project….

If you found this article informative and helpful, please consider following me for more blockchain and cryptocurrency-related content. You can also subscribe to my email list to receive updates on my latest articles and projects.

--

--