From 2dc5435c19b0302e4ad316ce5dba7c4c04e43933 Mon Sep 17 00:00:00 2001 From: Marenz Date: Tue, 27 Sep 2022 19:39:17 +0200 Subject: [PATCH] wipAdd VM Version Paris and new built in function ``prevrandao``Add VM Version Paris and new built in function ``prevrandao`` --- .circleci/soltest_all.sh | 2 +- Changelog.md | 7 +-- docs/cheatsheet.rst | 3 +- docs/grammar/SolidityLexer.g4 | 4 +- docs/units-and-global-variables.rst | 3 +- docs/using-the-compiler.rst | 3 ++ docs/yul.rst | 10 +++-- libevmasm/Instruction.cpp | 3 ++ libevmasm/Instruction.h | 3 +- libevmasm/SimplificationRule.h | 1 + liblangutil/EVMVersion.h | 10 +++-- libsolidity/analysis/TypeChecker.cpp | 29 +++++++++--- libsolidity/ast/Types.cpp | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 2 + .../codegen/ir/IRGeneratorForStatements.cpp | 9 +++- libyul/backends/evm/EVMDialect.cpp | 22 ++++++++- scripts/test_antlr_grammar.sh | 3 ++ test/EVMHost.cpp | 2 + test/evmc/evmc.h | 9 +++- .../prevrandao_pre_paris_function.sol | 21 +++++++++ .../difficulty_nowarn_pre_paris.sol | 6 +++ .../inlineAssembly/difficulty_reserved.sol | 18 ++++++++ .../inlineAssembly/difficulty_warn_paris.sol | 7 +++ .../prevrandao_nowarn_paris.sol | 6 +++ .../prevrandao_reserved_paris.sol | 20 +++++++++ .../prevrandao_warn_pre_paris.sol | 7 +++ .../types/magic_block_istanbul.sol | 3 -- ...ine_assembly_instructions_allowed_pure.sol | 1 + ...ine_assembly_instructions_allowed_view.sol | 4 +- ...embly_instructions_allowed_view_london.sol | 15 +++++++ ..._assembly_instructions_disallowed_pure.sol | 4 +- ...ly_instructions_disallowed_pure_london.sol | 45 +++++++++++++++++++ 32 files changed, 249 insertions(+), 34 deletions(-) create mode 100644 test/libsolidity/semanticTests/inlineAssembly/prevrandao_pre_paris_function.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_nowarn_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_reserved.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/difficulty_warn_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_nowarn_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_reserved_paris.sol create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/prevrandao_warn_pre_paris.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol diff --git a/.circleci/soltest_all.sh b/.circleci/soltest_all.sh index 3e29d1d2e..23663ce46 100755 --- a/.circleci/soltest_all.sh +++ b/.circleci/soltest_all.sh @@ -31,7 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)" # shellcheck source=scripts/common.sh source "${REPODIR}/scripts/common.sh" -EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london) +EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london paris) DEFAULT_EVM=london [[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]] OPTIMIZE_VALUES=(0 1) diff --git a/Changelog.md b/Changelog.md index 98b36aab8..37ae2583c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,12 +1,13 @@ ### 0.8.18 (unreleased) Language Features: + * Add support for ``prevrandao()`` which was introduced in EVM version to "Paris", supplanting ``difficulty`` in the process. Both can be used interchangeably. Compiler Features: -* Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode. -* Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode. -* Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. + * Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode. + * Standard JSON: Add a boolean field `settings.metadata.appendCBOR` that skips CBOR metadata from getting appended at the end of the bytecode. + * Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. Bugfixes: diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 3a7d478b1..244ebcf3a 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -8,7 +8,7 @@ Order of Precedence of Operators ================================ .. include:: types/operator-precedence-table.rst -.. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send +.. index:: assert, block, coinbase, difficulty, prevrandao, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, codehash, send Global Variables ================ @@ -33,6 +33,7 @@ Global Variables - ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty +- ``block.prevrandao`` (``uint``): randomness provided by the beacon chain - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index c47dc411c..b0dfca0c4 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -291,8 +291,8 @@ YulEVMBuiltin: | 'returndatacopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode' | 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid' | 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice' - | 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'gaslimit' - | 'basefee'; + | 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao' + | 'gaslimit' | 'basefee'; YulLBrace: '{' -> pushMode(YulMode); YulRBrace: '}' -> popMode; diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index b19396299..884fa2585 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -65,7 +65,7 @@ There are special variables and functions which always exist in the global namespace and are mainly used to provide information about the blockchain or are general-use utility functions. -.. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin +.. index:: abi, block, coinbase, difficulty, prevrandao, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin Block and Transaction Properties @@ -76,6 +76,7 @@ Block and Transaction Properties - ``block.chainid`` (``uint``): current chain id - ``block.coinbase`` (``address payable``): current block miner's address - ``block.difficulty`` (``uint``): current block difficulty +- ``block.prevrandao`` (``uint``): randomness provided by the beacon chain - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number - ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index cf5e1b768..7bf58fde4 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -172,6 +172,9 @@ at each version. Backward compatibility is not guaranteed between each version. the optimizer. - ``london`` (**default**) - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. +- ``paris`` + - The ``difficulty`` opcode was supplanted by the new opcode ``prevrandao`` (`EIP-4399 `_). + Both can be used interchangeably. ``prevrandao`` is a reserved keyword in yul code. .. index:: ! standard JSON, ! --standard-json diff --git a/docs/yul.rst b/docs/yul.rst index f6109a125..88f14dbbd 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -755,8 +755,8 @@ This document does not want to be a full description of the Ethereum virtual mac Please refer to a different document if you are interested in the precise semantics. Opcodes marked with ``-`` do not return a result and all others return exactly one value. -Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I`` and ``L`` are present since Frontier, Homestead, -Byzantium, Constantinople, Istanbul or London respectively. +Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L`` and ``P`` are present since Frontier, Homestead, +Byzantium, Constantinople, Istanbul, London or Paris respectively. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to but not including position ``b`` and ``storage[p]`` signifies the storage contents at slot ``p``. @@ -933,7 +933,11 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | number() | | F | current block number | +-------------------------+-----+---+-----------------------------------------------------------------+ -| difficulty() | | F | difficulty of the current block | +| difficulty() | | F | difficulty of the current block, supplanted by ``prevrandao()`` | +| | | | in evm version paris | ++-------------------------+-----+---+-----------------------------------------------------------------+ +| prevrandao() | | P | randomness provided by the beacon chain, supplants | +| | | | ``difficulty()`` starting with evm version paris | +-------------------------+-----+---+-----------------------------------------------------------------+ | gaslimit() | | F | block gas limit of the current block | +-------------------------+-----+---+-----------------------------------------------------------------+ diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp index e2ce48b7f..78eaefac3 100644 --- a/libevmasm/Instruction.cpp +++ b/libevmasm/Instruction.cpp @@ -77,6 +77,7 @@ std::map const solidity::evmasm::c_instructions = { "TIMESTAMP", Instruction::TIMESTAMP }, { "NUMBER", Instruction::NUMBER }, { "DIFFICULTY", Instruction::DIFFICULTY }, + { "PREVRANDAO", Instruction::PREVRANDAO }, { "GASLIMIT", Instruction::GASLIMIT }, { "CHAINID", Instruction::CHAINID }, { "SELFBALANCE", Instruction::SELFBALANCE }, @@ -223,6 +224,8 @@ static std::map const c_instructionInfo = { Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } }, { Instruction::TIMESTAMP, { "TIMESTAMP", 0, 0, 1, false, Tier::Base } }, { Instruction::NUMBER, { "NUMBER", 0, 0, 1, false, Tier::Base } }, +// { Instruction::PREVRANDAO, { "PREVRANDAO", 0, 0, 1, false, Tier::Base } }, +// TODO Replace with PREVRANDAO in the next breaking release { Instruction::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } }, { Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } }, { Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } }, diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h index 52bda8bf1..17ee8b4a7 100644 --- a/libevmasm/Instruction.h +++ b/libevmasm/Instruction.h @@ -84,7 +84,8 @@ enum class Instruction: uint8_t TIMESTAMP, ///< get the block's timestamp NUMBER, ///< get the block's number DIFFICULTY, ///< get the block's difficulty - GASLIMIT, ///< get the block's gas limit + PREVRANDAO = DIFFICULTY, ///< get randomness provided by the beacon chain + GASLIMIT = 0x45, ///< get the block's gas limit CHAINID, ///< get the config's chainid param SELFBALANCE, ///< get balance of the current account BASEFEE, ///< get the block's basefee diff --git a/libevmasm/SimplificationRule.h b/libevmasm/SimplificationRule.h index d548a00df..aef456968 100644 --- a/libevmasm/SimplificationRule.h +++ b/libevmasm/SimplificationRule.h @@ -123,6 +123,7 @@ struct EVMBuiltins static auto constexpr TIMESTAMP = PatternGenerator{}; static auto constexpr NUMBER = PatternGenerator{}; static auto constexpr DIFFICULTY = PatternGenerator{}; + static auto constexpr PREVRANDAO = PatternGenerator{}; static auto constexpr GASLIMIT = PatternGenerator{}; static auto constexpr CHAINID = PatternGenerator{}; static auto constexpr SELFBALANCE = PatternGenerator{}; diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h index c68441f01..0fa4b03f3 100644 --- a/liblangutil/EVMVersion.h +++ b/liblangutil/EVMVersion.h @@ -52,10 +52,11 @@ public: static EVMVersion istanbul() { return {Version::Istanbul}; } static EVMVersion berlin() { return {Version::Berlin}; } static EVMVersion london() { return {Version::London}; } + static EVMVersion paris() { return {Version::Paris}; } static std::optional fromString(std::string const& _version) { - for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london()}) + for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london(), paris()}) if (_version == v.name()) return v; return std::nullopt; @@ -77,6 +78,7 @@ public: case Version::Istanbul: return "istanbul"; case Version::Berlin: return "berlin"; case Version::London: return "london"; + case Version::Paris: return "paris"; } return "INVALID"; } @@ -90,6 +92,8 @@ public: bool hasChainID() const { return *this >= istanbul(); } bool hasSelfBalance() const { return *this >= istanbul(); } bool hasBaseFee() const { return *this >= london(); } + bool hasPrevRandao() const { return *this >= paris(); } + bool hasDifficulty() const { return *this < paris(); } bool hasOpcode(evmasm::Instruction _opcode) const; @@ -98,11 +102,11 @@ public: bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); } private: - enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London }; + enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London, Paris }; EVMVersion(Version _version): m_version(_version) {} - Version m_version = Version::London; + Version m_version = Version::Paris; }; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1025e6576..644588003 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -3286,18 +3286,33 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess) (memberName == "min" || memberName == "max") ) annotation.isPure = true; - else if (magicType->kind() == MagicType::Kind::Block && memberName == "chainid" && !m_evmVersion.hasChainID()) + else if (magicType->kind() == MagicType::Kind::Block) + { + if (memberName == "chainid" && !m_evmVersion.hasChainID()) m_errorReporter.typeError( 3081_error, _memberAccess.location(), "\"chainid\" is not supported by the VM version." ); - else if (magicType->kind() == MagicType::Kind::Block && memberName == "basefee" && !m_evmVersion.hasBaseFee()) - m_errorReporter.typeError( - 5921_error, - _memberAccess.location(), - "\"basefee\" is not supported by the VM version." - ); + else if (memberName == "basefee" && !m_evmVersion.hasBaseFee()) + m_errorReporter.typeError( + 5921_error, + _memberAccess.location(), + "\"basefee\" is not supported by the VM version." + ); + else if (memberName == "difficulty" && m_evmVersion.hasPrevRandao()) + m_errorReporter.warning( + 8417_error, + _memberAccess.location(), + "\"difficulty\" was renamed and supplanted by \"prevrandao\" in the VM version paris." + ); + else if (memberName == "prevrandao" && !m_evmVersion.hasPrevRandao()) + m_errorReporter.warning( + 9432_error, + _memberAccess.location(), + "\"prevrandao\" is not supported by the VM version and will be treated like \"difficulty\"." + ); + } } if ( diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 9c0179eda..e41f26abb 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -4059,6 +4059,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const {"timestamp", TypeProvider::uint256()}, {"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)}, {"difficulty", TypeProvider::uint256()}, + {"prevrandao", TypeProvider::uint256()}, {"number", TypeProvider::uint256()}, {"gaslimit", TypeProvider::uint256()}, {"chainid", TypeProvider::uint256()}, diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 461de5648..911ff3a7a 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1810,6 +1810,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) m_context << Instruction::TIMESTAMP; else if (member == "difficulty") m_context << Instruction::DIFFICULTY; + else if (member == "prevrandao") + m_context << Instruction::PREVRANDAO; else if (member == "number") m_context << Instruction::NUMBER; else if (member == "gaslimit") diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 30575930c..d9e011b30 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1822,8 +1822,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) define(_memberAccess) << "coinbase()\n"; else if (member == "timestamp") define(_memberAccess) << "timestamp()\n"; - else if (member == "difficulty") - define(_memberAccess) << "difficulty()\n"; + else if (member == "difficulty" || member == "prevrandao") + { + if (m_context.evmVersion().hasPrevRandao()) + define(_memberAccess) << "prevrandao()\n"; + else + define(_memberAccess) << "difficulty()\n"; + } else if (member == "number") define(_memberAccess) << "number()\n"; else if (member == "gaslimit") diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp index 71b9dba4c..1057b530d 100644 --- a/libyul/backends/evm/EVMDialect.cpp +++ b/libyul/backends/evm/EVMDialect.cpp @@ -118,12 +118,19 @@ set createReservedIdentifiers(langutil::EVMVersion _evmVersion) { return _instr == evmasm::Instruction::BASEFEE && _evmVersion < langutil::EVMVersion::london(); }; + // TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name + // prevrandao for VMs before paris. + auto prevRandAOException = [&](string const& _instrName) -> bool + { + // Using string comparison as the opcode is the same as for "difficulty" + return _instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris(); + }; set reserved; for (auto const& instr: evmasm::c_instructions) { string name = toLower(instr.first); - if (!baseFeeException(instr.second)) + if (!baseFeeException(instr.second) && !prevRandAOException(name)) reserved.emplace(name); } reserved += vector{ @@ -139,6 +146,17 @@ set createReservedIdentifiers(langutil::EVMVersion _evmVersion) map createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess) { + auto hasOpCode = [&](evmasm::Instruction _instr, string const& _instrName) -> bool + { + if ( + _instr == evmasm::Instruction::PREVRANDAO && + _instrName == "prevrandao" + ) + return _evmVersion.hasPrevRandao(); + + return _evmVersion.hasOpcode(_instr); + }; + map builtins; for (auto const& instr: evmasm::c_instructions) { @@ -152,7 +170,7 @@ map createBuiltins(langutil::EVMVersion _evmVe opcode != evmasm::Instruction::JUMP && opcode != evmasm::Instruction::JUMPI && opcode != evmasm::Instruction::JUMPDEST && - _evmVersion.hasOpcode(opcode) + hasOpCode(opcode, name) ) builtins.emplace(createEVMFunction(name, opcode)); } diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index 5745f01be..b5a48a7c9 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -121,6 +121,9 @@ done < <( grep -v -E 'revertStatement/non_called.sol' | # Skipping a test with "let basefee := ..." grep -v -E 'inlineAssembly/basefee_berlin_function.sol' | + # Skipping tests with "let prevrandao := ..." + grep -v -E 'inlineAssembly/prevrandao_pre_paris_function.sol' | + grep -v -E 'inlineAssembly/prevrandao_reserved_paris.sol' | # Skipping license error, unrelated to the grammar grep -v -E 'license/license_double5.sol' | grep -v -E 'license/license_hidden_unicode.sol' | diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp index 7c9a8f4dd..1d1018a25 100644 --- a/test/EVMHost.cpp +++ b/test/EVMHost.cpp @@ -122,6 +122,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm): m_evmRevision = EVMC_BERLIN; else if (_evmVersion == langutil::EVMVersion::london()) m_evmRevision = EVMC_LONDON; + else if (_evmVersion == langutil::EVMVersion::paris()) + m_evmRevision = EVMC_PARIS; else assertThrow(false, Exception, "Unsupported EVM version"); diff --git a/test/evmc/evmc.h b/test/evmc/evmc.h index c0d79d4e7..acefbd165 100644 --- a/test/evmc/evmc.h +++ b/test/evmc/evmc.h @@ -832,12 +832,19 @@ enum evmc_revision */ EVMC_LONDON = 9, + /** + * The Paris revision. + * + * https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md + */ + EVMC_PARIS = 10, + /** * The Shanghai revision. * * https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md */ - EVMC_SHANGHAI = 10, + EVMC_SHANGHAI = 11, /** The maximum EVM revision supported. */ EVMC_MAX_REVISION = EVMC_SHANGHAI, diff --git a/test/libsolidity/semanticTests/inlineAssembly/prevrandao_pre_paris_function.sol b/test/libsolidity/semanticTests/inlineAssembly/prevrandao_pre_paris_function.sol new file mode 100644 index 000000000..98915ba88 --- /dev/null +++ b/test/libsolidity/semanticTests/inlineAssembly/prevrandao_pre_paris_function.sol @@ -0,0 +1,21 @@ +contract C { + function f() public view returns (uint ret) { + assembly { + let prevrandao := sload(0) + ret := prevrandao + } + } + function g() public pure returns (uint ret) { + assembly { + function prevrandao() -> r { + r := 1000 + } + ret := prevrandao() + } + } +} +// ==== +// EVMVersion: 0 +// g() -> 1000 diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nowarn_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nowarn_pre_paris.sol new file mode 100644 index 000000000..02e16f04c --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_nowarn_pre_paris.sol @@ -0,0 +1,6 @@ +function f() view returns (uint) { + return block.difficulty; +} +// ==== +// EVMVersion: r { + r := 1000 + } + ret := difficulty() + } + } +} +// ---- +// ParserError 5568: (98-108): Cannot use builtin function name "difficulty" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/difficulty_warn_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_warn_paris.sol new file mode 100644 index 000000000..e59711394 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/difficulty_warn_paris.sol @@ -0,0 +1,7 @@ +function f() view returns (uint) { + return block.difficulty; +} +// ==== +// EVMVersion: >=paris +// ---- +// Warning 8417: (43-59): "difficulty" was renamed and supplanted by "prevrandao" in the VM version paris. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_nowarn_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_nowarn_paris.sol new file mode 100644 index 000000000..509d7ee34 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_nowarn_paris.sol @@ -0,0 +1,6 @@ +function f() view returns (uint) { + return block.prevrandao; +} +// ==== +// EVMVersion: >=paris +// ---- diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_reserved_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_reserved_paris.sol new file mode 100644 index 000000000..ea8489c65 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_reserved_paris.sol @@ -0,0 +1,20 @@ +contract C { + function f() public view returns (uint ret) { + assembly { + let prevrandao := sload(0) + ret := prevrandao + } + } + function g() public pure returns (uint ret) { + assembly { + function prevrandao() -> r { + r := 1000 + } + ret := prevrandao() + } + } +} +// ==== +// EVMVersion: >=paris +// ---- +// ParserError 5568: (98-108): Cannot use builtin function name "prevrandao" as identifier name. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_warn_pre_paris.sol b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_warn_pre_paris.sol new file mode 100644 index 000000000..9779adc37 --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/prevrandao_warn_pre_paris.sol @@ -0,0 +1,7 @@ +function f() view returns (uint) { + return block.prevrandao; +} +// ==== +// EVMVersion: =london +// EVMVersion: >=paris // ---- // Warning 5740: (94-1733): Unreachable code. // Warning 5740: (1746-1758): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol new file mode 100644 index 000000000..39a43ea62 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_london.sol @@ -0,0 +1,15 @@ +contract C { + function f() public view { + assembly { + // Renamed in paris + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: =london +// ---- +// Warning 5740: (94-1733): Unreachable code. +// Warning 5740: (1746-1758): Unreachable code. +// Warning 5740: (1801-1810): Unreachable code. +// Warning 5740: (1978-2244): Unreachable code. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol index f9a652fdb..cabfefc0c 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure.sol @@ -32,7 +32,7 @@ contract C { pop(coinbase()) pop(timestamp()) pop(number()) - pop(difficulty()) + pop(prevrandao()) pop(gaslimit()) // These two are disallowed too but the error suppresses other errors. @@ -42,7 +42,7 @@ contract C { } } // ==== -// EVMVersion: >=london +// EVMVersion: >=paris // ---- // Warning 5740: (672-1083): Unreachable code. // TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol new file mode 100644 index 000000000..114b9f313 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_london.sol @@ -0,0 +1,45 @@ +contract C { + function f() public pure { + assembly { + // Renamed in paris + pop(difficulty()) + } + } +} +// ==== +// EVMVersion: =london +// ---- +// Warning 5740: (672-1083): Unreachable code. +// TypeError 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (101-113): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (130-135): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (153-162): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (180-190): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (208-221): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (239-247): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (265-276): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (294-308): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (322-345): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (362-376): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (394-409): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (427-446): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (464-489): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (507-536): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (554-584): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (602-630): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 8961: (644-659): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (672-682): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (695-708): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (721-737): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (750-769): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 8961: (782-804): Function cannot be declared as pure because this expression (potentially) modifies the state. +// TypeError 2527: (821-830): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (848-857): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (875-883): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (901-911): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (929-941): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (959-969): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (987-998): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (1016-1024): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (1042-1054): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (1072-1082): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".