Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we generate multiple random number in ethereum?

I want my smart contract to return 7 or 8 UNIQUE random numbers ranging from 1 to 100 upon calling the contract. What can be the best approach to obtain such result?

like image 938
Joe Mutti Avatar asked Sep 23 '18 14:09

Joe Mutti


People also ask

How do you generate a random number in solidity?

Step 1: Take the instance of now, the msg. sender, and an incrementing nonce. Step 2: “pack” the inputs and use keccak256() to convert into 256-bit hash. Step 3: Convert that hash to an uint, and then use % 100 to take only the last 2 digits.

Is chainlink VRF truly random?

What Does Chainlink Do? The Chainlink VRF (Verifiable Random Function) is a decentralized oracle network that blockchain developers use as a tamper-proof random number generator to build reliable smart contracts by producing a provably fair and verifiable source of randomness.

Is smart contract in ethereum has how many address?

Solidity has a type called address , which holds an Ethereum 20-byte address. Every account and smart contract on the Ethereum blockchain has a unique address and can send and receive Ether (ETH) to and from this address.


3 Answers

Probably if you are trying to build roulettes, lotteries, and card games using the Ethereum blockchain, as the Ethereum blockchain is deterministic, it imposes certain difficulties for those who have chosen to write their own pseudo-random number generator (PRNG).

Some Vulnerable Methods Currently Used

If you are using the block variables like block.coinbase, block.difficulty, block.timestamp etc.. as the source of entropy, all these block variables can be manipulated by miners, so they cannot be used as a source of entropy because of the miners’ incentive. As the block variables are obviously shared within the same block, you can easily use internal messages to yield the same outcome.

Other methods are like using blockhash of current or some past block or blockhash of a past block combined with a private seed. block.blockhash(block.number) function is used in these cases. However, at the moment of transaction execution in the EVM, the blockhash of the block that is being created is not yet known for obvious reasons and the EVM will always yield zero. If we are trying it with the blockhash of a previous block, an attacker can make an exploit contract with the same code in order to call the target contract via an internal message. The “random” numbers for the two contracts will be the same.

Even if we combine the blockhash with a private seed, being transparent in nature, the blockchain must not be used to store secrets in plaintext. It is trivial to extract the value of the private variable pointer from the contract storage and supply it as an argument to an exploit.

Some Areas Worth Exploring

  • External oracles
  • Signidice
  • Commit–reveal approach

With External oracles like Oraclize, smart contracts can request data from web APIs such as currency exchange rates, weather forecasts, and stock prices (like random.org). The key drawback of this approach is that it is centralized. Will Oraclize daemon tamper with the results? Can we trust random.org?

Instead of Oraclize, we can also use BTCRelay which is a bridge between Ethereum and Bitcoin blockchains. Using BTCRelay, smart contracts in the Ethereum blockchain can request future Bitcoin blockhashes and use them as a source of entropy.

Signidice is an algorithm based on cryptographic signatures that can be used for random number generation in smart contracts involving only two parties: the player and the house. The algorithm works as follows:

  • The player makes a bet by calling a smart contract.
  • The house sees the bet, signs it with its private key, and sends the signature to the smart contract.
  • The smart contract verifies the signature using the known public key.
  • This signature is then used to generate a random number.

Commit–reveal approach consists of two phases:

  • A “commit” stage, when the parties submit their cryptographically protected secrets to the smart contract.
  • A “reveal” stage, when the parties announce cleartext seeds, the smart contract verifies that they are correct, and the seeds are used to generate a random number.

A better implementation of the commit–reveal approach is Randao. Commit–reveal can be combined with future blockhashes to make it more secure.

This pretty much covers all the methods for random number generation using Ethereum.

like image 139
Joseph T F Avatar answered Oct 18 '22 00:10

Joseph T F


Like Raghav said, random numbers on the blockchain are hard. The public nature of the network makes it very hard to generate a number that cannot be pre-calculated.

With that said, one of the best solutions is to use an oracle that gets the random number from an external (read: non-blockchain based) source. Take a look at this guide. The Ethtroll Dapp is a good example of this, so take a look at the code here. They use Oraclize to get a random number from Random.org.

An issue with using an oracle is the centralization factor. If you set up your Dapp in the way I have described above, you are at the mercy of a rouge employee at two different centralized services—Oraclize and Random.org. Though it would be unlikely for someone to manipulate either of these sources, people will perform irrational acts for potential economic gain.

like image 4
Shane Fontaine Avatar answered Oct 18 '22 00:10

Shane Fontaine


Use a Chainlink VRF.

There are a number of issues with using the blockhash or similar as the method of random seeding. If an attacker knows the blockhash before your contract, they can use that information to gain a malicious advantage on whatever it is you're trying to do. An oracle can help here, but they are a central source of failure and must be able to prove they are random.

You need to have an oracle network that can:

  1. Prove that the numbers generated are random.
  2. Have enough oracles/nodes that even if one fails/is corrupt, your smart contract will persist.

At this time, the example below shows how to solve #1. You can solve #2 by pulling from a sufficient number of nodes who support the Chainlink VRF.

For an exact implementation, see this answer from a similar question.

You'll want to make a request to a node with a function that takes a seed generated by you:

 function rollDice(uint256 userProvidedSeed) public returns (bytes32 requestId) {
        require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
        uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and blockhash
        bytes32 _requestId = requestRandomness(keyHash, fee, seed);
        emit RequestRandomness(_requestId, keyHash, seed);
        return _requestId;
    }

And when the value is returned, you'll mod it by 100 and add 1. You'll need to call this 7 or 8 times if you want 7 or 8 random numbers.

function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
        uint256 d6Result = randomness.mod(100).add(1);
        emit RequestRandomnessFulfilled(requestId, randomness);
    }

like image 4
Patrick Collins Avatar answered Oct 17 '22 23:10

Patrick Collins