EIP-4399: Supplant DIFFICULTY opcode with RANDOM

This is the discussion topic for EIP-4399: Supplant DIFFICULTY opcode with RANDOM.
This EIP proposes to supplant the DIFFICULTY opcode with the RANDOM opcode within the upgrade to PoS (a.k.a. the Merge)


I think strong consideration should be given to adding a new RANDOM opcode instead of replacing the DIFFICULTY opcode. When writing solidity contracts that use the difficulty and random field it would make it easier to audit when code may depend on the semantics of one over the other.

1 Like

The changes introduced by this EIP are applied beginning with TRANSITION_POS_BLOCK (the first PoS block in the network). Beginning with TRANSITION_POS_BLOCK, the DIFFICULTY opcode will start to return 0 as per the deprecation of the difficulty field introduced by EIP-3675. The idea of preserving the DIFFICULTY instruction number for the new RANDOM opcode is in removing backwards incompatible change introduced by EIP-3675 with respect to existing smart contracts. Existing smart contracts will be able to use the EVM instruction with the same number as a source of randomness outputs disregarding the Merge has happened or not. Although, they will have to take in account the change in the size and the nature of these outputs post-Merge as it’s stated in the EIP.

This improvement seems like it will lead developers down a disingenuous path. As I understand it, the current method of randomness in ETH 2 is RANDAO (correct me if I’m wrong).

This would mean:

  1. We are baking an application built on top of ETH into ETH itself (seems incorrect)
  2. We are leaking a potential security vulnerability to developers. One hack of the DAO and every application using this randomness is potentially corrupted.
  3. Additionally, we’ve seem hacks perivously of people using block.difficulty so changing the name I’m not sure makes sense on ETH 1 either. See a previous hack. Obviously, something like this is not even in consideration for ETH 1, since it would give the miners too much power.

Imagine someone being able to hack every single randomness-based application on ETH, lotteries, raffles, etc in a single go. Like a defi protocal hack times infinity. We are talking billions of dollars here.

Seems like a small change, but I think the naming convention would be drastically misleading, and a massive threat to the entire system.

This is my current understanding, but maybe I’m missing something.

The mechanism of accumulating randomness in the beacon chain is inspired by the RANDAO, there is no DAO that is used to obtain randomness seeds. The detailed explanation of how does it work in the beacon chain is here. The power of each validator with respect to the randao computation is significantly limited on the beacon chain.

Security Considerations section of the EIP states that the randomness output that is exposed by the RANDOM opcode becomes known to network participants when the parent block gets published, application developers MUST take this into consideration. In that regard the new opcode doesn’t differ much from the DIFFICULTY as block.difficulty is known to the miner of the block in advance and should there be an incentive the difficulty value could easily be shared or even sold.

1 Like

Since DIFFICULTY will not return anything meaningful in POS (there is no block difficulty in POS), contracts that use block.difficulty will break after the merge. Therefore, the DIFFICULTY opcode has to be changed to return something.

So the question becomes, “What do we replace it with?”. The EIP states that:

Given prior analysis on the usage of DIFFICULTY, the value returned by the opcode mixed with other values is a common pattern used by smart contracts to obtain randomness.

In other words, given that pseudo-randomness generation is the most common use of block.difficulty in contracts, and pseudo-randomness is generated as part of the beacon chain, changing DIFFICULTY to return the RANDOM value is reasonable for backwards compatibility.

Furthermore, under “Security Considerations”, it states:

The RANDOM opcode in the PoS network should be considered as a source of randomness output of a higher strength than the output provided by either the BLOCKHASH or the DIFFICULTY opcode in the PoW network.

However, the randomness output returned by the RANDOM opcode is revealed to the network within the parent block.

So if anything, it’s slightly improving the pseudo-randomness generated in contracts using block.difficulty. However, it’s still not a true source of randomness in much the same way as block.difficulty is not.

1 Like

Thanks for the context Alex, and thanks for the info @mkalinin.

It sounds like PRANDOM would be a better opcode then since this is a pseudo-randomness method. I think having the opcode be purely RANDOM would be incredibly dangerous.

I’ve seen enough hacks from projects thinking that the difficulty is a secure method of randomness, and I’d rather not bake a bad practice into Ethereum.

Ideally, we choose a different name entirely.

I don’t think that adding a P prefix to the name of this opcode changes anything. Careful implementer like you are would read and grok all the implications before using a thing. Others would rely on DIFFICULTY and BLOCKHASH as a source of randomness (thinking that they are strong enough) despite of warnings made here and there. Additionally, is there a system that uses true randomness? It seems like pseudo randomness is used in most of the cases.

“Careful implementer like you”

I don’t think we should be implementing conventions that make things more complicated. Developer experience is death by 1,000 cuts, and this is one of those things that could be easily avoided.

“Oh wait, the RANDOM opcode isn’t actually random?”

I’d really rather us not introduce concepts that are confusing.

And yes, there are systems that use True randomness like Chainlink VRF.

VRF is pseudo-random by its definition. In the beacon chain what is called randao_reveal is basically the output of VRF. And the output that is proposed to be exposed in the EVM is a mix of VRF outputs of different oracles for millions of slots starting from genesis.

There are two weaknesses. 1) validator may skip its reveal by refusing to propose a block and reduce the strength of the output by a bit 2) privacy issue, randao_reveal hence accumulated randomness output becomes known to the validator in a slight advance. These two weaknesses are presented in Chainlink VRF as well.

There is no issue with respect to the pseudo-random nature of the output. And I don’t understand how P prefix or any other prefixes would emphasise the existing weaknesses. They should be written in the spec and learned by developers who is going to use it.

They should be written in the spec and learned by developers who is going to use it.

I think we will just disagree on that point and see what others think. To me, it seems naming something that we know to be misleading is counterproductive.

As per your two points against Chainlink VRF, this may be true in the current implementation, but new versions are being worked on, including threshold signatures which will remove these weaknesses, and other similar devices could also be created that are better versions of randomness for smart contracts than those built into the ETH system.

So, I’m wondering what disassemblers and debugging tools should report on seeing this opcode. This isn’t the first time an opcode has been renamed, but it’s the first time it’s been renamed to something with such a different meaning. It’s like, are these tools now going to have to be aware of what hardfork a given contract was written for…?