EIP-4399: Supplant DIFFICULTY opcode with RANDOM

Thank you for the explanation. So, the PREVRANDAO value is the first param (get_randao_mix(state, epoch)) in the following formula, source
mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
But why not just return the mix value as the randomness in evm?

A mix value of the previous block is returned. If we’d return this value from current block then block builders would have to get the reveal in advance (which is insecure) to be able to build a block while the previous value is available on chain.

oh, I see, the insecure attack vectors come from the MEV-boost, PBS. Hope to see the RANDAO(n) function supported in evm and solidity as soon as possible. Only in this way, the PREVRANAO value could be used by dapps. How about we start drafting now?

What vector are you referring to? Usage of the PREVRANDAO opcode has its security implications but I would not say this operation is completely useless, could you elaborate on that?

  1. From my point of view, the insecurity of revealing in advance is, it would incur attacks like DoS from the block builder.

  2. Suppose we have a lottery dapp which contains two methods: roll and claim.
    Alice roll the dice @ slot n, and we use the K + N + ε slot PREVRANDAO as the randomness. But if we have only have PREVRANAO, how to claim rewards? You can get this randao value only when the proposer is propose the K + N + ε slot.

The randao mix is known multiple blocks in advance to a proposer or colluding set of proposers who are proposing sequential blocks. An entity who has 50% of validator share, for example, has a 100% chance of knowing the randao mix as soon as the previous block is published, a 50% chance of knowing it when the block before that is published, a 25% chance of knowing it when the block before that is published, etc.

For frequent games, the liklihood of a proposer knowing the mix in advance for at least one iteration of the game can get quite high. For this reason, you should always separate the “bet” and the “roll” by a significant number of blocks.

Also, keep in mind that for high stakes games, it may be worthwhile for an attacker to skip producing a block they know will be a loser (sacrificing fees and block reward) in exchange for getting a second chance at rolling the die. For a block proposer who is proposing two blocks in a row where the “roll” is scheduled for the first block, they can choose between two rolls by choosing to sacrifice the first block (missed slot) or publishing the first block.

For all of these reasons, one must take extreme care when using randao mix for randomness on chain. It has utility in some cases, but it is exploitable by block producers in various ways and you should ensure that the profit of exploitation is lower than the opportunity cost (skipped blocks).

Thanks for your tips. I’ve noticed these risks already. My question is how dapps can make use of the RANDAO value technically if the RANDAO(n) function has not been supported?

Ah, you would only be able to require that the randomness is used at least n blocks in the future. Since you can’t get historical randao values, you will have to settle for “the randao value of whatever block the transaction was included in”.

yeah, that’s the problem. Take the lottery Dapp as an example. When you try to claim the rewards in slot n, you are gonna use the slot n randao value which actually has been revealed to all users before slot n.
Cuz, users just need to calcuate the value according to PREVRANDAO[n] = PREVRANDAO[n-1] XOR (SHA256(RANDAO_REVEAL(n-1)).

Attackers just need to wait for the right randao value to claim the lottery rewards for sure.
That’s why the RANDAO(n) function is indispensable for security in my opnion.

1 Like

RANDAO(n) I suspect is valuable, but it has a couple caveats that need to be ironed out before it can be included (plus, it needs an EIP champion to push it through).

Should n refer to block or slot? Slots can be empty (no RANDAO reveal), which makes block number appealing, but block number doesn’t have a well defined point in time in the future (which is useful in some contexts).

Regardless of whether you choose block or slot for n, at the least the block builder can choose between two options for that block. If a validator produces multiple blocks in a row, they get more attempts (combinatorial number I think).

1 Like

There are two different questions. Let’s discuss them one by one. The first question is
Suppose we have a lottery dapp which contains two methods: roll and claim.
Alice roll the dice @ slot n, and lottery contract uses the K + N + ε slot PREVRANDAO as the randomness. But how to claim rewards? Cuz, you can obtain this randao value only when the proposer is proposing the K + N + ε slot. Which means, user’s claim transaction must be sealed in the slot K + N + ε. If missed, user cannot claim rewards due to the inaccessible of the randomness.

What happens if slot K + N + ε - 1 is missed (thus PREVRANDAO points at K + N + ε - 2)?
What happens if block K + N + ε is missed or empty, thus you cannot execute anything in that slot?

1 Like

ah, that’s my second question. Let’s discuss that later. Now, suppose the slot was never missed, how the users could claim the rewards? They could claim the rewards only when the proposer is proposing that block @ slot n. Am I right?

With the current RANDAO mechanism, and using a design like proposed, yes. Having RANDAO(n) is certainly useful, as it allows you to specify a block to use. Without that, the mechanism would likely just be “the first transaction that targets this contract after block n will determine which block the RANDAO is from”.

1 Like

Yup. As for the slot n or block n, if the RANDAO(n) is supported, I believe, both solutions are ok.

However, block n would be easier for dapp developers. Cuz, each block has a corresponding slot for sure, developers don’t need to consider the missed slot situation. But I don’t know if it’s feasible for execution client of returning the PRERANDAO(n) @ block n in evm?

If dapps choose block K + N + ε as the randomness source after block n, the security of the random number could be guaranteed.

1 Like

They still definitely need to consider missed slots. The proposer of block n or n-1 (depending on how it is implemented) can decide to propose or miss, which will change the RANDAO(n) result. If the proposer proposes m blocks in a row, I believe they can choose between 2^m different die rolls.

oh, I see, really appreciate your explanations. It seems the randao value in evm is not secured for dapps especially when a large amount of money is involved.

It can be usefully used for a source of randomness, but you have to be incredibly careful with how you use it and the specific design of your system, money at stake, etc. My general advice to people is to not try to build randomness on-chain for anything that has any substantial value. It is just too easy to get it wrong.

Just FYI added Solidity Deep Dive: New Opcode 'Prevrandao'. Looking forward to further EIPs regarding specific Randao values.

6 Likes

sorry to revive this but I think what some might’ve considered as bikeshedding was worth it. It being named “prevrandao” made me dive into the rabbit hole and ultimately end up here

1 Like