From 81268e336573721819e39fbb3fefbc9344ad176c Mon Sep 17 00:00:00 2001 From: r0qs Date: Wed, 27 Dec 2023 17:50:28 -0300 Subject: [PATCH] Add blobhash high-level global function. --- Changelog.md | 1 + docs/cheatsheet.rst | 5 +++- docs/units-and-global-variables.rst | 3 +++ docs/using-the-compiler.rst | 1 + libsolidity/analysis/GlobalContext.cpp | 15 ++++++++--- libsolidity/analysis/GlobalContext.h | 3 ++- libsolidity/ast/Types.cpp | 1 + libsolidity/ast/Types.h | 1 + libsolidity/codegen/ExpressionCompiler.cpp | 6 ++++- .../codegen/ir/IRGeneratorForStatements.cpp | 2 ++ libsolidity/interface/CompilerStack.cpp | 5 +++- scripts/test_antlr_grammar.sh | 1 + test/libsolidity/Assembly.cpp | 2 +- .../SolidityExpressionCompiler.cpp | 25 ++++++++++++++++++- test/libsolidity/ViewPureChecker.cpp | 2 ++ .../builtinFunctions/blobhash.sol | 18 +++++++++++++ .../blobhash_shadow_resolution.sol | 12 +++++++++ .../semanticTests/state/blobhash.sol | 14 +++++++++++ .../semanticTests/state/uncalled_blobhash.sol | 12 +++++++++ .../blobhash_function_pre_cancun.sol | 11 ++++++++ .../blobhash_function_shadow_warning.sol | 12 +++++++++ .../globalFunctions/blobhash_no_call.sol | 10 ++++++++ .../blobhash_not_declared_pre_cancun.sol | 10 ++++++++ .../blobhash_var_pre_cancun.sol | 9 +++++++ .../blobhash_var_shadow_warning.sol | 11 ++++++++ ...l => blobhash_pre_cancun_not_declared.sol} | 0 .../blobhash_pre_cancun_not_reserved.sol | 19 ++++++++++++++ .../syntaxTests/viewPureChecker/blobhash.sol | 13 ++++++++++ .../viewPureChecker/blobhash_not_pure.sol | 12 ++++++--- .../builtin_blobhash_restrict_warning.sol | 10 ++++++++ 30 files changed, 234 insertions(+), 12 deletions(-) create mode 100644 test/libsolidity/semanticTests/builtinFunctions/blobhash.sol create mode 100644 test/libsolidity/semanticTests/builtinFunctions/blobhash_shadow_resolution.sol create mode 100644 test/libsolidity/semanticTests/state/blobhash.sol create mode 100644 test/libsolidity/semanticTests/state/uncalled_blobhash.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_function_pre_cancun.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_function_shadow_warning.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_no_call.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_not_declared_pre_cancun.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_var_pre_cancun.sol create mode 100644 test/libsolidity/syntaxTests/globalFunctions/blobhash_var_shadow_warning.sol rename test/libsolidity/syntaxTests/inlineAssembly/{blobhash_pre_cancun.sol => blobhash_pre_cancun_not_declared.sol} (100%) create mode 100644 test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/blobhash.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/builtin_blobhash_restrict_warning.sol diff --git a/Changelog.md b/Changelog.md index 741e64f3e2d9..0cfa621e802a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Language Features: * Introduce global ``block.blobbasefee`` for retrieving the blob base fee of the current block. + * Introduce global function ``blobhash(uint)`` for retrieving versioned hashes of blobs, akin to the homonymous Yul builtin. * Yul: Introduce builtin ``blobbasefee()`` for retrieving the blob base fee of the current block. * Yul: Introduce builtin ``blobhash()`` for retrieving versioned hashes of blobs associated with the transaction. diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index e6b632dae4b6..2b68d7311982 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -56,13 +56,16 @@ Members of ``address`` returns ``false`` on failure - ``
.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure -.. index:: blockhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp +.. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp .. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin Block and Transaction Properties ================================ - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks +- ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. + A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes + of the SHA256 hash of the KZG commitment (`EIP-4844 `_). - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index f95c9c5290d8..a0422c32dfa9 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -74,6 +74,9 @@ Block and Transaction Properties -------------------------------- - ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block when ``blocknumber`` is one of the 256 most recent blocks; otherwise returns zero +- ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. + A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes + of the SHA256 hash of the KZG commitment (`EIP-4844 `_). - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 60fbd0884a89..93bdff8661bf 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -178,6 +178,7 @@ at each version. Backward compatibility is not guaranteed between each version. - Smaller code size and gas savings due to the introduction of ``push0`` (see `EIP-3855 `_). - ``cancun`` - The block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) can be accessed via the global ``block.blobbasefee`` or ``blobbasefee()`` in inline assembly. + - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). .. index:: ! standard JSON, ! --standard-json .. _compiler-api: diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 8f0ce963499b..628b903617de 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -59,17 +59,18 @@ int magicVariableToID(std::string const& _name) else if (_name == "tx") return -26; else if (_name == "type") return -27; else if (_name == "this") return -28; + else if (_name == "blobhash") return -29; else solAssert(false, "Unknown magic variable: \"" + _name + "\"."); } -inline std::vector> constructMagicVariables() +inline std::vector> constructMagicVariables(langutil::EVMVersion _evmVersion) { static auto const magicVarDecl = [](std::string const& _name, Type const* _type) { return std::make_shared(magicVariableToID(_name), _name, _type); }; - return { + std::vector> magicVariableDeclarations = { magicVarDecl("abi", TypeProvider::magic(MagicType::Kind::ABI)), magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, StateMutability::Pure)), magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, StateMutability::Pure)), @@ -101,11 +102,19 @@ inline std::vector> constructMag FunctionType::Options::withArbitraryParameters() )), }; + + if (_evmVersion >= langutil::EVMVersion::cancun()) + magicVariableDeclarations.push_back( + magicVarDecl("blobhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlobHash, StateMutability::View)) + ); + + return magicVariableDeclarations; } } -GlobalContext::GlobalContext(): m_magicVariables{constructMagicVariables()} +GlobalContext::GlobalContext(langutil::EVMVersion _evmVersion): + m_magicVariables{constructMagicVariables(_evmVersion)} { } diff --git a/libsolidity/analysis/GlobalContext.h b/libsolidity/analysis/GlobalContext.h index 69344537cae7..3aa5e76e8966 100644 --- a/libsolidity/analysis/GlobalContext.h +++ b/libsolidity/analysis/GlobalContext.h @@ -23,6 +23,7 @@ #pragma once +#include #include #include #include @@ -47,7 +48,7 @@ class GlobalContext GlobalContext(GlobalContext const&) = delete; GlobalContext& operator=(GlobalContext const&) = delete; - GlobalContext(); + GlobalContext(langutil::EVMVersion _evmVersion); void setCurrentContract(ContractDefinition const& _contract); void resetCurrentContract() { m_currentContract = nullptr; } MagicVariableDeclaration const* currentThis() const; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 77538f485b1c..0af9f105fb1b 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3075,6 +3075,7 @@ std::string FunctionType::richIdentifier() const case Kind::ABIEncodeCall: id += "abiencodecall"; break; case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break; case Kind::ABIDecode: id += "abidecode"; break; + case Kind::BlobHash: id += "blobhash"; break; case Kind::MetaType: id += "metatype"; break; } id += "_" + stateMutabilityToString(m_stateMutability); diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index fd1b6a7d3df3..7bbd2f075875 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1270,6 +1270,7 @@ class FunctionType: public Type SetGas, ///< modify the default gas value for the function call SetValue, ///< modify the default value transfer for the function call BlockHash, ///< BLOCKHASH + BlobHash, ///< BLOBHASH AddMod, ///< ADDMOD MulMod, ///< MULMOD ArrayPush, ///< .push() to a dynamically sized array in storage diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c96d8bdea641..494d106c833f 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1035,9 +1035,13 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) break; } case FunctionType::Kind::BlockHash: + case FunctionType::Kind::BlobHash: { acceptAndConvert(*arguments[0], *function.parameterTypes()[0], true); - m_context << Instruction::BLOCKHASH; + if (function.kind() == FunctionType::Kind::BlockHash) + m_context << Instruction::BLOCKHASH; + else + m_context << Instruction::BLOBHASH; break; } case FunctionType::Kind::AddMod: diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index deed7f80c18c..57414da93ba1 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1498,11 +1498,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) case FunctionType::Kind::GasLeft: case FunctionType::Kind::Selfdestruct: case FunctionType::Kind::BlockHash: + case FunctionType::Kind::BlobHash: { static std::map functions = { {FunctionType::Kind::GasLeft, "gas"}, {FunctionType::Kind::Selfdestruct, "selfdestruct"}, {FunctionType::Kind::BlockHash, "blockhash"}, + {FunctionType::Kind::BlobHash, "blobhash"}, }; solAssert(functions.find(functionType->kind()) != functions.end()); diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index b4e3cf7f389a..9b5c87818bf2 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -235,6 +235,9 @@ void CompilerStack::setEVMVersion(langutil::EVMVersion _version) if (m_stackState >= ParsedAndImported) solThrow(CompilerError, "Must set EVM version before parsing."); m_evmVersion = _version; + // GlobalContext depends on evmVersion since the Cancun hardfork. + // Therefore, we reset it whenever we set a new EVM version, ensuring that the context is never reused with a mismatched version. + m_globalContext.reset(); } void CompilerStack::setEOFVersion(std::optional _version) @@ -469,7 +472,7 @@ bool CompilerStack::analyze() if (source->ast && !syntaxChecker.checkSyntax(*source->ast)) noErrors = false; - m_globalContext = std::make_shared(); + m_globalContext = std::make_shared(m_evmVersion); // We need to keep the same resolver during the whole process. NameAndTypeResolver resolver(*m_globalContext, m_evmVersion, m_errorReporter, experimentalSolidity); for (Source const* source: m_sourceOrder) diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh index 6ed57f2db9f2..ea00cc0f6e0e 100755 --- a/scripts/test_antlr_grammar.sh +++ b/scripts/test_antlr_grammar.sh @@ -128,6 +128,7 @@ done < <( grep -v -E 'inlineAssembly/prevrandao_disallowed_function_post_paris.sol' | # Skipping a test with "let blobhash := ..." grep -v -E 'inlineAssembly/blobhash_pre_cancun.sol' | + grep -v -E 'inlineAssembly/blobhash_pre_cancun_not_reserved.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/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index ccad7d49d12e..7def76e69fe2 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -63,7 +63,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr _sourceCode) Scoper::assignScopes(*sourceUnit); BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit)); - GlobalContext globalContext; + GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); solAssert(!Error::containsErrors(errorReporter.errors()), ""); diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index a171a5be0571..1df1d9430086 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -42,6 +42,7 @@ using namespace solidity::evmasm; using namespace solidity::langutil; +using namespace solidity::test; namespace solidity::frontend::test { @@ -124,7 +125,7 @@ bytes compileFirstExpression( ErrorList errors; ErrorReporter errorReporter(errors); - GlobalContext globalContext; + GlobalContext globalContext(solidity::test::CommonOptions::get().evmVersion()); Scoper::assignScopes(*sourceUnit); BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit)); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter, false); @@ -656,6 +657,28 @@ BOOST_AUTO_TEST_CASE(blockhash) BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); } +BOOST_AUTO_TEST_CASE( + blobhash, + *boost::unit_test::precondition(minEVMVersionCheck(EVMVersion::cancun())) +) +{ + char const* sourceCode = R"( + contract test { + function f() public { + blobhash(3); + } + } + )"; + + bytes code = compileFirstExpression(sourceCode, {}, {}); + + bytes expectation({ + uint8_t(Instruction::PUSH1), 0x03, + uint8_t(Instruction::BLOBHASH) + }); + BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); +} + BOOST_AUTO_TEST_CASE(gas_left) { char const* sourceCode = R"( diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp index a26511a0c944..3d0e024da83b 100644 --- a/test/libsolidity/ViewPureChecker.cpp +++ b/test/libsolidity/ViewPureChecker.cpp @@ -53,6 +53,8 @@ BOOST_AUTO_TEST_CASE(environment_access) }; if (solidity::test::CommonOptions::get().evmVersion().hasStaticCall()) view.emplace_back("address(0x4242).staticcall(\"\")"); + if (solidity::test::CommonOptions::get().evmVersion().hasBlobHash()) + view.emplace_back("blobhash(7)"); // ``block.blockhash`` and ``blockhash`` are tested separately below because their usage will // produce warnings that can't be handled in a generic way. diff --git a/test/libsolidity/semanticTests/builtinFunctions/blobhash.sol b/test/libsolidity/semanticTests/builtinFunctions/blobhash.sol new file mode 100644 index 000000000000..445a011bda54 --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/blobhash.sol @@ -0,0 +1,18 @@ +contract C { + function f() public view returns(bytes32) { + return blobhash(0); + } + function g() public view returns(bytes32) { + return blobhash(1); + } + function h() public view returns(bytes32) { + // NOTE: blobhash(2) should return 0 since EVMHost has only two blob hashes injected in the block the transaction is being executed. + return blobhash(2); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0x0100000000000000000000000000000000000000000000000000000000000001 +// g() -> 0x0100000000000000000000000000000000000000000000000000000000000002 +// h() -> 0x00 diff --git a/test/libsolidity/semanticTests/builtinFunctions/blobhash_shadow_resolution.sol b/test/libsolidity/semanticTests/builtinFunctions/blobhash_shadow_resolution.sol new file mode 100644 index 000000000000..6a141cb970fd --- /dev/null +++ b/test/libsolidity/semanticTests/builtinFunctions/blobhash_shadow_resolution.sol @@ -0,0 +1,12 @@ +contract C { + function blobhash(uint256 index) public pure returns(bytes32) { + return bytes32(index); + } + function f() public pure returns(bytes32) { + return blobhash(3); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0x03 diff --git a/test/libsolidity/semanticTests/state/blobhash.sol b/test/libsolidity/semanticTests/state/blobhash.sol new file mode 100644 index 000000000000..f27b4072be25 --- /dev/null +++ b/test/libsolidity/semanticTests/state/blobhash.sol @@ -0,0 +1,14 @@ +contract C { + function f(uint _index) public returns (bytes32) { + return blobhash(_index); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f(uint256): 0 -> 0x0100000000000000000000000000000000000000000000000000000000000001 +// f(uint256): 1 -> 0x0100000000000000000000000000000000000000000000000000000000000002 +// f(uint256): 2 -> 0x00 +// f(uint256): 255 -> 0x00 +// f(uint256): 256 -> 0x00 +// f(uint256): 257 -> 0x00 diff --git a/test/libsolidity/semanticTests/state/uncalled_blobhash.sol b/test/libsolidity/semanticTests/state/uncalled_blobhash.sol new file mode 100644 index 000000000000..df81a46918eb --- /dev/null +++ b/test/libsolidity/semanticTests/state/uncalled_blobhash.sol @@ -0,0 +1,12 @@ +contract C { + function f() public returns (bytes32) { + // NOTE: The `tx_context.blob_hashes` is injected into EVMHost with the following hashes, indexed accordingly: + // 0 -> 0x0100000000000000000000000000000000000000000000000000000000000001 + // 1 -> 0x0100000000000000000000000000000000000000000000000000000000000002 + return (blobhash)(0); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// f() -> 0x0100000000000000000000000000000000000000000000000000000000000001 diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_pre_cancun.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_pre_cancun.sol new file mode 100644 index 000000000000..e5904f4e67bd --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_pre_cancun.sol @@ -0,0 +1,11 @@ +contract C { + function blobhash(uint256 index) public pure returns(bytes32) { + return bytes32(index); + } + function f() public pure returns(bytes32) { + return blobhash(2); + } +} +// ==== +// EVMVersion: <=shanghai +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_shadow_warning.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_shadow_warning.sol new file mode 100644 index 000000000000..5469df9e6a03 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_function_shadow_warning.sol @@ -0,0 +1,12 @@ +contract C { + function blobhash(uint256 index) public pure returns(bytes32) { + return bytes32(index); + } + function f() public pure returns(bytes32) { + return blobhash(2); + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2319: (17-117): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_no_call.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_no_call.sol new file mode 100644 index 000000000000..369ea047806f --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_no_call.sol @@ -0,0 +1,10 @@ +contract C +{ + function f() public pure { + blobhash; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 6133: (52-60): Statement has no effect. diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_not_declared_pre_cancun.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_not_declared_pre_cancun.sol new file mode 100644 index 000000000000..a62f830150f4 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_not_declared_pre_cancun.sol @@ -0,0 +1,10 @@ +contract C +{ + function f() public pure { + blobhash; + } +} +// ==== +// EVMVersion: <=shanghai +// ---- +// DeclarationError 7576: (52-60): Undeclared identifier. Did you mean "blockhash"? diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_pre_cancun.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_pre_cancun.sol new file mode 100644 index 000000000000..42b54dc666a8 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_pre_cancun.sol @@ -0,0 +1,9 @@ +contract C { + function f() public pure returns (bool) { + bool blobhash = true; + return blobhash; + } +} +// ==== +// EVMVersion: <=shanghai +// ---- diff --git a/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_shadow_warning.sol b/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_shadow_warning.sol new file mode 100644 index 000000000000..f60378e8df31 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/blobhash_var_shadow_warning.sol @@ -0,0 +1,11 @@ +contract C +{ + function f() public pure returns (bool) { + bool blobhash = true; + return blobhash; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2319: (67-80): This declaration shadows a builtin symbol. diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol similarity index 100% rename from test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun.sol rename to test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_declared.sol diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol new file mode 100644 index 000000000000..1ac24cc6497a --- /dev/null +++ b/test/libsolidity/syntaxTests/inlineAssembly/blobhash_pre_cancun_not_reserved.sol @@ -0,0 +1,19 @@ +contract C { + function f() public pure returns (uint ret) { + assembly { + let blobhash := 1 + ret := blobhash + } + } + function g() public pure returns (uint ret) { + assembly { + function blobhash() -> r { + r := 1000 + } + ret := blobhash() + } + } +} +// ==== +// EVMVersion: <=shanghai +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/blobhash.sol b/test/libsolidity/syntaxTests/viewPureChecker/blobhash.sol new file mode 100644 index 000000000000..4de6929aa84f --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/blobhash.sol @@ -0,0 +1,13 @@ +contract C { + function f() public view returns (bytes32 ret){ + assembly { + ret := blobhash(0) + } + } + function g() public view returns (bytes32) { + return blobhash(0); + } +} +// ==== +// EVMVersion: >=cancun +// ---- diff --git a/test/libsolidity/syntaxTests/viewPureChecker/blobhash_not_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/blobhash_not_pure.sol index 2e38ddedb8f8..d03e336a6009 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/blobhash_not_pure.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/blobhash_not_pure.sol @@ -1,9 +1,15 @@ contract C { - function f() public pure { - assembly { pop(blobhash(0)) } + function f() public pure returns (bytes32 ret){ + assembly { + ret := blobhash(0) + } + } + function g() public pure returns (bytes32) { + return blobhash(0); } } // ==== // EVMVersion: >=cancun // ---- -// TypeError 2527: (67-78): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (103-114): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view". +// TypeError 2527: (195-206): 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/builtin_blobhash_restrict_warning.sol b/test/libsolidity/syntaxTests/viewPureChecker/builtin_blobhash_restrict_warning.sol new file mode 100644 index 000000000000..18a0f58641da --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/builtin_blobhash_restrict_warning.sol @@ -0,0 +1,10 @@ +contract C { + function g() public { + bytes32 w = blobhash(0); + w; + } +} +// ==== +// EVMVersion: >=cancun +// ---- +// Warning 2018: (17-88): Function state mutability can be restricted to view