1

How can I generate a random number within the smart contract without external oracles. Maybe based on the block number or is there any other element that can be used for that?

2 Answers2

1

You probably shouldn't do this

By default, just don't.

Why you shouldn't

Using on-chain data (eg. the block number) as entropy to generate a random number gives an advantage to miners. For example, a miner can decide to not integrate a transaction to its next wanna-be block, because the outcome is not in its favor. The transaction will be integrated later in another block, thus leading to a second chance for the miner.

There are other examples of how such procedure can be broken.

When it might be okay

To quote this answer:

As a general rule, BLOCKHASH can only be safely used for a random number if the total amount of value resting on the quality of that randomness is lower than what a miner earns by mining a single block.

In other words, random number generation without external calls can only be used for low stake applications.

philippe_b
  • 421
  • 5
  • 9
0

There are some approaches on GitHub, this one looks promising and seems, as you have suggested, to rely on the block timestamp to generate random numbers:

https://github.com/axiomzen/eth-random

The contract itself is rather simple (although I cannot estimate how expensive its execution is):

pragma solidity ^0.4.4;

contract Random {
  uint64 _seed = 0;

  // return a pseudo random number between lower and upper bounds
  // given the number of previous blocks it should hash.
  function random(uint64 upper) public returns (uint64 randomNumber) {
    _seed = uint64(sha3(sha3(block.blockhash(block.number), _seed), now));
    return _seed % upper;
  }
}
javahippie
  • 225
  • 1
  • 9
  • This appears to be the block hash, which isn't ideal but it's better than the block timestamp, which can be manipulated by the miner at no cost. – Edmund Edgar Dec 06 '17 at 11:38
  • I think it is not just the block hash. They are also having a call to now, which should be the same as block.timestamp. – javahippie Dec 06 '17 at 12:13
  • Sorry, yes, you're right, I missed that. This is a bad idea, they'd be safer with just the block hash. – Edmund Edgar Dec 06 '17 at 12:42
  • 1
    I agree with you, and in a way also the maintainers of the Repo agree: "Firstly, the block timestamp is not terribly unpredictable and yet it's one of the strongest sources of entropy available in the blockchain along with contract's internal seed [..] If security is a main focus, it may be best to look into purchasing an oracle solution" – javahippie Dec 06 '17 at 12:49
  • block.blockhash(block.number) always returns 0x0 so it doesn't add any randomness. https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620 – medvedev1088 Feb 21 '18 at 15:41