EIP-4399: PREVRANDAO — where on-chain randomness comes from
The EVM is deterministic — there's no 'random' opcode, because every node must compute the same result. Contracts that wanted randomness abused the DIFFICULTY opcode, which was weak and miner-manipulable — and which vanished at the Merge. EIP-4399 repurposes that opcode to expose the beacon chain's RANDAO, giving contracts a real (if biasable) randomness beacon.
- the EVM's determinism
- the Merge & the beacon chain
Paris / the Merge, September 2022. Here’s a question that sounds trivial and isn’t: how does a smart contract get a random number? On an ordinary computer you’d call a random function. But the EVM is deterministic — every node re-executes every transaction and must reach the identical result, or they’d disagree on the state. A genuine random() opcode is therefore impossible: whatever it returned would have to be the same on every machine, which is the opposite of random. Contracts still wanted randomness, so they reached for the nearest thing that looked unpredictable — and the Merge both broke that hack and offered something better. EIP-4399 is that swap. Let’s derive it.
The problem: determinism forbids randomness
Because every node must compute the same state, the EVM can’t have a true source of randomness — any value it produces has to be reproducible by everyone. So there’s no random opcode, and contracts that wanted unpredictability improvised. The favourite hack was the DIFFICULTY opcode (0x44), which returned the block’s proof-of-work difficulty — a number that varied block to block and felt unpredictable. But it was weak randomness: miners could nudge it, and it wasn’t designed to be unguessable. Worse, at the Merge, proof-of-work ended and there was no difficulty at all — the hack’s foundation simply disappeared.
→ Step 2: there is — the beacon chain’s RANDAO.
Repurpose the opcode to return RANDAO
The beacon chain already maintains a shared randomness value called the RANDAO A randomness value the beacon chain accumulates by mixing in a contribution from each block proposer (a reveal from their private, pre-committed sequence). No single validator controls the result, and it's the same for every node. : each block, the proposer reveals a value that gets mixed (XOR-folded) into the running RANDAO, so no one validator controls it and every node holds the same number. EIP-4399 simply exposes it to the EVM — by reusing the now-meaningless DIFFICULTY opcode (0x44), renamed PREVRANDAO The Merge-era meaning of opcode 0x44 (formerly DIFFICULTY): it returns the previous block's RANDAO value, a 32-byte number from the beacon chain, available to contracts as a randomness beacon. . Now PREVRANDAO returns the previous block’s RANDAO — a 32-byte value from the beacon chain — so a contract has a built-in randomness beacon that every node agrees on, without a new opcode slot or a special mechanism.
→ Step 3: know exactly how weak it is.
The payoff — and the sharp edge
PREVRANDAO is a genuine, network-agreed randomness beacon, and for low-stakes uses (picking a daily featured item, tie-breaking, jitter) it’s perfectly fine. But it is not strong randomness, and using it as if it were is a classic bug. The reason: the proposer bias A block proposer learns the RANDAO value that will apply to its slot one epoch in advance, and can choose to skip (not propose) its slot — forfeiting the reward but changing which RANDAO applies. So the proposer has limited but real influence over the 'random' outcome. means the party building the block knows the value ahead of time and can grind it a little by skipping a slot. So for anything high-value — a lottery, a large random allocation — contracts should layer a commit-reveal scheme on top or use an external verifiable random function (like Chainlink VRF). PREVRANDAO is the floor, not the ceiling.