ethereum / solidity

Solidity, the Smart Contract Programming Language
https://soliditylang.org
GNU General Public License v3.0
23.37k stars 5.78k forks source link

feat: introduce `block.prevrandao` as alias for `block.difficulty` #13512

Closed pcaversaccio closed 1 year ago

pcaversaccio commented 2 years ago

Summary

EIP-4399 renames the DIFFICULTY (0x44) opcode to PREVRANDAO (0x44). The return value of the DIFFICULTY (0x44) instruction after this change is the output of the randomness beacon provided by the beacon chain.

For reference, I implemented this feature in Vyper here.

axic commented 2 years ago

Should be consider not making it a blank alias (like we had for sha256 vs sha3), but enable one or the other based on the evmVersion selected?

I think that would make more sense, as it gives an indication to the user of a potential issue. Of course one can deploy a contract compiled for an older evm version, so it is not bulletproof.

pcaversaccio commented 2 years ago

@axic I get your point - for that reason actually, we put a warning depending on the EVM version used (see here).

cameel commented 2 years ago

I think it might be better only to switch between which one is the default depending on the EVM version but still accept both. Otherwise it would be breaking regarding the asm import (we're currently implementing). And would also change assembly output which probably should also be considered breaking since tools may depend on that.

AliMohammadnia commented 2 years ago

Hi guys I am Ali I want to learn blockchain programming How should I practice and what programming language should I use????❤️

ekpyron commented 2 years ago

Yeah, the opcode name in assembly output is something to think about. What's your thoughts about making this a full hard switch depending on the evm version setting? I.e. remove block.difficulty entirely for Paris and also only emit and parse prevrandao in assembly - while keeping everything as is for <Paris? The error message for the use of block.difficulty or the opcode with evm version set to paris could mention that you can just specify a different evm version to make it work again.

Given that you could restore the previous behaviour easily, makes it less of a severe breaking change. We could also hold off on making paris the default evm version until we have tooling feedback on this...

EDIT: also promoting this to must have since #13517 depends on a decision on this.

ekpyron commented 2 years ago

Just to clarify - this will entail:

Anything else I missed?

mryalamanchi commented 2 years ago

Let's assume to remove the block.difficulty if it's paris version and replace it with block.prevrandao.

What would happen to the Contracts that were previously using block.difficulty and decided to upgrade (using upgradable SM architecture) from >=0.8.x to the latest one which has this change, and suddenly the compiler throws warning or doesn't compile?

cameel commented 2 years ago

@mryalamanchi It would not affect upgrades (i.e. storage layout) at all. The compiler should still produce the same exact bytecode even with the new name.

At the EVM level the way the opcode works will change immediately with the merge whether we do anything or not. The change in the compiler is simply to reflect that change in meaning but does not itself change that meaning.

cameel commented 2 years ago

So far the biggest problem seems to be the fact that this would affect portability of third-party libraries. They would no longer be able to provide code that uses block.difficulty() and still works when EVM is set to paris. For this reason we're likely to just keep both names available until the next breaking release.

cameel commented 2 years ago

Decision from the call today: we'll do it the same way Vyper does, i.e.

ekpyron commented 2 years ago

Just as a small addition: on the Yul level this will mean adding prevrandao as pseudo-builtin only for now, i.e. to introduce it, but to also allow shadowing it by a user-defined function called prevrandao (while emitting a warning). We should then promote it to a proper builtin (disallowing any user-defined functions with that name) with 0.9.

Marenz commented 2 years ago

the EVM version will decide whether we output one or the other,

Aren't we outputting the opcode anyway, which is staying the same?

Marenz commented 2 years ago

Started working on this in https://github.com/ethereum/solidity/tree/paris-oh-paris (no pr yet)

cameel commented 2 years ago

Aren't we outputting the opcode anyway, which is staying the same?

I meant the name of the opcode, which does change. It's the numeric value used in bytecode (0x44) that stays the same. So bytecode will not change but Solidity, Yul and EVM asm output will.

immujahidkhan commented 7 months ago

uint256 seed = uint256(keccak256(abi.encode(block.timestamp, totalTickets)));