Using randomness safely
Due to the deterministic nature of blockchain execution, it is not possible to generate random numbers or values by calling a random function within a smart contract. Therefore, smart contract developers need to find alternative ways to introduce randomness into their applications, such as using external sources of randomness (oracles) or cryptographic techniques (commit-reveal schemes).
Bad ways to create randomness
Some developers use unreliable sources of randomness for projects that are in development or where being able to predict the output of the randomness doesn't cause problems. These are some examples of ways to create randomness that are not appropriate for production applications because they can be predicted or manipulated:
-
Timestamps: The timestamp of the local computer is a commonly-used source of randomness on non-blockchain software, but it is not appropriate for blockchain software or anywhere security is a concern. Timestamps may be predictable, and bakers can manipulate them by delaying when they create blocks. On Tezos, the timestamp of the block is only in seconds, providing limited entropy.
Also, in the current version of the Tezos protocol, calls to get the current time (such as the LIGO
Tezos.get_now
function) always receive the timestamp of the previous block plus a fixed value, regardless of the time that the block was actually created. Providing the time in this way eliminates straightforward manipulations but makes it easier to predict the timestamp of a future block. -
Hashes and addresses: Account and contract addresses and operation hashes may seem to be random, but they are not. For example, addresses are computed based on the operation group hash and an origination index (starting from 0 which is increased for every origination operation in the group). It can therefore be easily manipulated by the creator of the operation which is no better than trusting them. For this reason, deploying a contract and using its address is not a good way to obtain a random value.
-
Exchange rates: Some developers use currency exchange rates provided by off-chain oracles as sources of randomness. However, they provide only a small amount of entropy and are also vulnerable to manipulation by the entities behind the oracle. Exchange rates are also subject to manipulation by entities who block certain transactions related to the oracle.
-
Bad randomness oracles: Anyone can provide an off-chain oracle and claim that it provides truly random values. However, it's hard to generate truly random values at all, and even harder to prove that they are truly random and immune to manipulation. Don't blindly trust an oracle, even if you find that many contracts use it already. A bad randomness oracle may stop working and make your contract fail or be under the control of a single person who then gains full control over all the outcomes of your contract that rely on it.
-
Combining multiple bad sources of randomness: It might seem like combining two or more of the above bad sources may improve the quality of the randomness, but in fact it also increases the risk that an entity can manipulate the outcome.
Keep in mind that bad actors don't need to predict the actual random value to make an attack based on a bad source of randomness; they only need to be able to predict which outcome is more likely to significantly increase the chance of getting an outcome that benefits them.
Good ways to create randomness
Ideally, and to protect against the vulnerabilities described above, contracts should not rely on randomness. However, if randomness is necessary, consider these approaches:
-
Combine random values provided by every participant: You can use timelocks and a commit-and-reveal scheme to allow multiple people to contribute random values, reveal them later, and use these values as a source of entropy. This type of scheme is difficult to do well, because it requires complex programming and quick action from the participants.
-
Use a good randomness oracle: It is, in theory, possible to create a good off-chain random Oracle. Chainlink offers a randomness Oracle based on a verifiable random function (VRF). However, this oracle is not available on Tezos. Also, any oracle relies on the trustworthiness of the operators.