diff --git a/Changelog.md b/Changelog.md
index f42e948ebbce..bfd04e7f7796 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,6 +1,8 @@
### 0.8.24 (unreleased)
Language Features:
+ * Introduce global ``block.blobbasefee`` for retrieving the blob base fee of the current block.
+ * Yul: Introduce builtin ``blobbasefee()`` for retrieving the blob base fee of the current block.
Compiler Features:
diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst
index 2f0c1a251f4d..e6b632dae4b6 100644
--- a/docs/cheatsheet.rst
+++ b/docs/cheatsheet.rst
@@ -56,7 +56,7 @@ 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;basefree, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp
+.. index:: blockhash, 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
@@ -64,6 +64,7 @@ Block and Transaction Properties
- ``blockhash(uint blockNumber) returns (bytes32)``: hash of the given block - only works for 256 most recent blocks
- ``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
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` that will be removed in the next breaking release
diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4
index 0452f9fa0bb6..b46af906164b 100644
--- a/docs/grammar/SolidityLexer.g4
+++ b/docs/grammar/SolidityLexer.g4
@@ -305,7 +305,7 @@ YulEVMBuiltin:
| 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid'
| 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice'
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao'
- | 'gaslimit' | 'basefee';
+ | 'gaslimit' | 'basefee' | 'blobbasefee';
YulLBrace: '{' -> pushMode(YulMode);
YulRBrace: '}' -> popMode;
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index d2256884eb48..f95c9c5290d8 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -67,7 +67,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, prevrandao, 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, block;basefee, block;blobbasefee, msg, data, gas, sender, value, gas price, origin
Block and Transaction Properties
@@ -75,6 +75,7 @@ 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
- ``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
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty (``EVM < Paris``). For other EVM versions it behaves as a deprecated alias for ``block.prevrandao`` (`EIP-4399 `_ )
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 0adcbf4132bb..60fbd0884a89 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -176,6 +176,8 @@ at each version. Backward compatibility is not guaranteed between each version.
- Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_).
- ``shanghai`` (**default**)
- 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.
.. index:: ! standard JSON, ! --standard-json
.. _compiler-api:
diff --git a/docs/yul.rst b/docs/yul.rst
index 0e50d137761c..fd792999a993 100644
--- a/docs/yul.rst
+++ b/docs/yul.rst
@@ -752,8 +752,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``, ``L`` and ``P`` are present since Frontier,
-Homestead, Byzantium, Constantinople, Istanbul, London or Paris respectively.
+Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P`` and ``N`` are present since Frontier,
+Homestead, Byzantium, Constantinople, Istanbul, London, Paris or Cancun 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``.
@@ -919,6 +919,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a
+-------------------------+-----+---+-----------------------------------------------------------------+
| basefee() | | L | current block's base fee (EIP-3198 and EIP-1559) |
+-------------------------+-----+---+-----------------------------------------------------------------+
+| blobbasefee() | | N | current block's blob base fee (EIP-7516 and EIP-4844) |
++-------------------------+-----+---+-----------------------------------------------------------------+
| origin() | | F | transaction sender |
+-------------------------+-----+---+-----------------------------------------------------------------+
| gasprice() | | F | gas price of the transaction |
diff --git a/libevmasm/Instruction.cpp b/libevmasm/Instruction.cpp
index 174d12b5e355..23d2667318d9 100644
--- a/libevmasm/Instruction.cpp
+++ b/libevmasm/Instruction.cpp
@@ -81,6 +81,7 @@ std::map const solidity::evmasm::c_instructions =
{ "CHAINID", Instruction::CHAINID },
{ "SELFBALANCE", Instruction::SELFBALANCE },
{ "BASEFEE", Instruction::BASEFEE },
+ { "BLOBBASEFEE", Instruction::BLOBBASEFEE },
{ "POP", Instruction::POP },
{ "MLOAD", Instruction::MLOAD },
{ "MSTORE", Instruction::MSTORE },
@@ -230,6 +231,7 @@ static std::map const c_instructionInfo =
{ Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } },
{ Instruction::SELFBALANCE, { "SELFBALANCE", 0, 0, 1, false, Tier::Low } },
{ Instruction::BASEFEE, { "BASEFEE", 0, 0, 1, false, Tier::Base } },
+ { Instruction::BLOBBASEFEE, { "BLOBBASEFEE", 0, 0, 1, false, Tier::Base } },
{ Instruction::POP, { "POP", 0, 1, 0, false, Tier::Base } },
{ Instruction::MLOAD, { "MLOAD", 0, 1, 1, true, Tier::VeryLow } },
{ Instruction::MSTORE, { "MSTORE", 0, 2, 0, true, Tier::VeryLow } },
diff --git a/libevmasm/Instruction.h b/libevmasm/Instruction.h
index 2fddb11d80ea..cf4f3df1440f 100644
--- a/libevmasm/Instruction.h
+++ b/libevmasm/Instruction.h
@@ -89,6 +89,7 @@ enum class Instruction: uint8_t
CHAINID, ///< get the config's chainid param
SELFBALANCE, ///< get balance of the current account
BASEFEE, ///< get the block's basefee
+ BLOBBASEFEE = 0x4a, ///< get the block's blob basefee
POP = 0x50, ///< remove item from stack
MLOAD, ///< load word from memory
diff --git a/libevmasm/SemanticInformation.cpp b/libevmasm/SemanticInformation.cpp
index 1971d9d45bb8..fcd948e8b656 100644
--- a/libevmasm/SemanticInformation.cpp
+++ b/libevmasm/SemanticInformation.cpp
@@ -473,6 +473,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
case Instruction::CALLVALUE:
case Instruction::CHAINID:
case Instruction::BASEFEE:
+ case Instruction::BLOBBASEFEE:
case Instruction::GAS:
case Instruction::GASPRICE:
case Instruction::EXTCODESIZE:
diff --git a/libevmasm/SimplificationRule.h b/libevmasm/SimplificationRule.h
index e970068fbd7e..50b69d69abc0 100644
--- a/libevmasm/SimplificationRule.h
+++ b/libevmasm/SimplificationRule.h
@@ -127,6 +127,7 @@ struct EVMBuiltins
static auto constexpr CHAINID = PatternGenerator{};
static auto constexpr SELFBALANCE = PatternGenerator{};
static auto constexpr BASEFEE = PatternGenerator{};
+ static auto constexpr BLOBBASEFEE = PatternGenerator{};
static auto constexpr POP = PatternGenerator{};
static auto constexpr MLOAD = PatternGenerator{};
static auto constexpr MSTORE = PatternGenerator{};
diff --git a/liblangutil/EVMVersion.cpp b/liblangutil/EVMVersion.cpp
index 24ef0673d8b9..78a98d2669cc 100644
--- a/liblangutil/EVMVersion.cpp
+++ b/liblangutil/EVMVersion.cpp
@@ -49,6 +49,8 @@ bool EVMVersion::hasOpcode(Instruction _opcode) const
return hasSelfBalance();
case Instruction::BASEFEE:
return hasBaseFee();
+ case Instruction::BLOBBASEFEE:
+ return hasBlobBaseFee();
default:
return true;
}
diff --git a/liblangutil/EVMVersion.h b/liblangutil/EVMVersion.h
index b68e9546a1aa..02e4e34f3839 100644
--- a/liblangutil/EVMVersion.h
+++ b/liblangutil/EVMVersion.h
@@ -101,6 +101,7 @@ class EVMVersion:
bool hasChainID() const { return *this >= istanbul(); }
bool hasSelfBalance() const { return *this >= istanbul(); }
bool hasBaseFee() const { return *this >= london(); }
+ bool hasBlobBaseFee() const { return *this >= cancun(); }
bool hasPrevRandao() const { return *this >= paris(); }
bool hasPush0() const { return *this >= shanghai(); }
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 5c28d3cd2a78..11812878a5da 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -3409,6 +3409,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
_memberAccess.location(),
"\"basefee\" is not supported by the VM version."
);
+ else if (memberName == "blobbasefee" && !m_evmVersion.hasBlobBaseFee())
+ m_errorReporter.typeError(
+ 1006_error,
+ _memberAccess.location(),
+ "\"blobbasefee\" is not supported by the VM version."
+ );
else if (memberName == "prevrandao" && !m_evmVersion.hasPrevRandao())
m_errorReporter.warning(
9432_error,
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 7b3e42143804..77538f485b1c 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -4116,7 +4116,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
{"number", TypeProvider::uint256()},
{"gaslimit", TypeProvider::uint256()},
{"chainid", TypeProvider::uint256()},
- {"basefee", TypeProvider::uint256()}
+ {"basefee", TypeProvider::uint256()},
+ {"blobbasefee", TypeProvider::uint256()}
});
case Kind::Message:
return MemberList::MemberMap({
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index 517f49c35331..c96d8bdea641 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -1886,6 +1886,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
m_context << Instruction::CHAINID;
else if (member == "basefee")
m_context << Instruction::BASEFEE;
+ else if (member == "blobbasefee")
+ m_context << Instruction::BLOBBASEFEE;
else if (member == "data")
m_context << u256(0) << Instruction::CALLDATASIZE;
else if (member == "sig")
diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp
index a5196366fd30..deed7f80c18c 100644
--- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp
+++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp
@@ -1895,6 +1895,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
define(_memberAccess) << "chainid()\n";
else if (member == "basefee")
define(_memberAccess) << "basefee()\n";
+ else if (member == "blobbasefee")
+ define(_memberAccess) << "blobbasefee()\n";
else if (member == "data")
{
IRVariable var(_memberAccess);
diff --git a/libyul/AsmAnalysis.cpp b/libyul/AsmAnalysis.cpp
index ed4187540e76..5fc5c55c8501 100644
--- a/libyul/AsmAnalysis.cpp
+++ b/libyul/AsmAnalysis.cpp
@@ -727,6 +727,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
errorForVM(7721_error, "only available for Istanbul-compatible");
else if (_instr == evmasm::Instruction::BASEFEE && !m_evmVersion.hasBaseFee())
errorForVM(5430_error, "only available for London-compatible");
+ else if (_instr == evmasm::Instruction::BLOBBASEFEE && !m_evmVersion.hasBlobBaseFee())
+ errorForVM(6679_error, "only available for Cancun-compatible");
else if (_instr == evmasm::Instruction::PC)
m_errorReporter.error(
2450_error,
diff --git a/libyul/backends/evm/EVMDialect.cpp b/libyul/backends/evm/EVMDialect.cpp
index 47130fd6c46d..12ffb0f649dd 100644
--- a/libyul/backends/evm/EVMDialect.cpp
+++ b/libyul/backends/evm/EVMDialect.cpp
@@ -120,6 +120,13 @@ std::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
+ // blobbasefee for VMs before cancun.
+ auto blobBaseFeeException = [&](evmasm::Instruction _instr) -> bool
+ {
+ return _instr == evmasm::Instruction::BLOBBASEFEE && _evmVersion < langutil::EVMVersion::cancun();
+ };
+
// 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 = [&](std::string const& _instrName) -> bool
@@ -132,7 +139,11 @@ std::set createReservedIdentifiers(langutil::EVMVersion _evmVersion)
for (auto const& instr: evmasm::c_instructions)
{
std::string name = toLower(instr.first);
- if (!baseFeeException(instr.second) && !prevRandaoException(name))
+ if (
+ !baseFeeException(instr.second) &&
+ !blobBaseFeeException(instr.second) &&
+ !prevRandaoException(name)
+ )
reserved.emplace(name);
}
reserved += std::vector{
diff --git a/scripts/error_codes.py b/scripts/error_codes.py
index 4aff6b85e80d..d4e9e5486665 100755
--- a/scripts/error_codes.py
+++ b/scripts/error_codes.py
@@ -202,7 +202,7 @@ def examine_id_coverage(top_dir, source_id_to_file_names, new_ids_only=False):
"4591", # "There are more than 256 warnings. Ignoring the rest."
# Due to 3805, the warning lists look different for different compiler builds.
"1834", # Unimplemented feature error, as we do not test it anymore via cmdLineTests
- "5430", # basefee being used in inline assembly for EVMVersion < london
+ "6679", # blobbasefee being used in inline assembly for EVMVersion < cancun
"1180", # SMTChecker, covered by CL tests
"2339", # SMTChecker, covered by CL tests
"2961", # SMTChecker, covered by CL tests
diff --git a/scripts/test_antlr_grammar.sh b/scripts/test_antlr_grammar.sh
index 4dde11bf7dac..290a044eb847 100755
--- a/scripts/test_antlr_grammar.sh
+++ b/scripts/test_antlr_grammar.sh
@@ -121,6 +121,8 @@ done < <(
grep -v -E 'revertStatement/non_called.sol' |
# Skipping a test with "let basefee := ..."
grep -v -E 'inlineAssembly/basefee_berlin_function.sol' |
+ # Skipping a test with "let blobbasefee := ..."
+ grep -v -E 'inlineAssembly/blobbasefee_shanghai_function.sol' |
# Skipping tests with "let prevrandao := ..."
grep -v -E 'inlineAssembly/prevrandao_allowed_function_pre_paris.sol' |
grep -v -E 'inlineAssembly/prevrandao_disallowed_function_post_paris.sol' |
diff --git a/test/EVMHost.cpp b/test/EVMHost.cpp
index 2bc1da96525e..813d28fdbf78 100644
--- a/test/EVMHost.cpp
+++ b/test/EVMHost.cpp
@@ -136,6 +136,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
tx_context.chain_id = evmc::uint256be{1};
// The minimum value of basefee
tx_context.block_base_fee = evmc::bytes32{7};
+ // The minimum value of blobbasefee
+ tx_context.blob_base_fee = evmc::bytes32{1};
// Reserve space for recording calls.
if (!recorded_calls.capacity())
diff --git a/test/libsolidity/ViewPureChecker.cpp b/test/libsolidity/ViewPureChecker.cpp
index 03b2b421b4eb..a26511a0c944 100644
--- a/test/libsolidity/ViewPureChecker.cpp
+++ b/test/libsolidity/ViewPureChecker.cpp
@@ -92,6 +92,26 @@ BOOST_AUTO_TEST_CASE(environment_access)
TypeError,
"\"block.blockhash()\" has been deprecated in favor of \"blockhash()\""
);
+
+ std::string baseFeeContract = "contract C { function f() view public { block.basefee; } }";
+ if (!solidity::test::CommonOptions::get().evmVersion().hasBaseFee())
+ CHECK_ERROR(
+ baseFeeContract,
+ TypeError,
+ "\"basefee\" is not supported by the VM version."
+ );
+ else
+ CHECK_SUCCESS_NO_WARNINGS(baseFeeContract);
+
+ std::string blobBaseFeeContract = "contract C { function f() view public { block.blobbasefee; } }";
+ if (!solidity::test::CommonOptions::get().evmVersion().hasBlobBaseFee())
+ CHECK_ERROR(
+ blobBaseFeeContract,
+ TypeError,
+ "\"blobbasefee\" is not supported by the VM version."
+ );
+ else
+ CHECK_SUCCESS_NO_WARNINGS(blobBaseFeeContract);
}
BOOST_AUTO_TEST_CASE(address_staticcall)
diff --git a/test/libsolidity/semanticTests/inlineAssembly/blobbasefee_shanghai_function.sol b/test/libsolidity/semanticTests/inlineAssembly/blobbasefee_shanghai_function.sol
new file mode 100644
index 000000000000..d06457133e36
--- /dev/null
+++ b/test/libsolidity/semanticTests/inlineAssembly/blobbasefee_shanghai_function.sol
@@ -0,0 +1,21 @@
+contract C {
+ function f() public view returns (uint ret) {
+ assembly {
+ let blobbasefee := 999
+ ret := blobbasefee
+ }
+ }
+ function g() public pure returns (uint ret) {
+ assembly {
+ function blobbasefee() -> r {
+ r := 1000
+ }
+ ret := blobbasefee()
+ }
+ }
+}
+// ====
+// EVMVersion: <=shanghai
+// ----
+// f() -> 999
+// g() -> 1000
diff --git a/test/libsolidity/semanticTests/state/block_blobbasefee.sol b/test/libsolidity/semanticTests/state/block_blobbasefee.sol
new file mode 100644
index 000000000000..23da779e40f2
--- /dev/null
+++ b/test/libsolidity/semanticTests/state/block_blobbasefee.sol
@@ -0,0 +1,17 @@
+contract C {
+ function f() public view returns (uint) {
+ return block.blobbasefee;
+ }
+ function g() public view returns (uint ret) {
+ assembly {
+ ret := blobbasefee()
+ }
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// f() -> 1
+// g() -> 1
+// f() -> 1
+// g() -> 1
diff --git a/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol
new file mode 100644
index 000000000000..0bab7e36c74e
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inlineAssembly/blobbasefee_reserved_cancun.sol
@@ -0,0 +1,12 @@
+contract C {
+ function f() public view returns (uint ret) {
+ assembly {
+ let blobbasefee := sload(0)
+ ret := blobbasefee
+ }
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// ParserError 5568: (98-109): Cannot use builtin function name "blobbasefee" as identifier name.
diff --git a/test/libsolidity/syntaxTests/types/magic_block_basefee_error.sol b/test/libsolidity/syntaxTests/types/magic_block_basefee_error.sol
index b723d0aeeb2b..3e1650ad88b9 100644
--- a/test/libsolidity/syntaxTests/types/magic_block_basefee_error.sol
+++ b/test/libsolidity/syntaxTests/types/magic_block_basefee_error.sol
@@ -2,8 +2,15 @@ contract C {
function f() public view returns (uint) {
return block.basefee;
}
+ function g() public view returns (uint ret) {
+ assembly {
+ ret := basefee()
+ }
+ }
}
// ====
-// EVMVersion: <=berlin
+// EVMVersion: =berlin
// ----
// TypeError 5921: (74-87): "basefee" is not supported by the VM version.
+// TypeError 5430: (183-190): The "basefee" instruction is only available for London-compatible VMs (you are currently compiling for "berlin").
+// DeclarationError 8678: (176-192): Variable count for assignment to "ret" does not match number of values (1 vs. 0)
diff --git a/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_cancun.sol b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_cancun.sol
new file mode 100644
index 000000000000..a639abda71ee
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_cancun.sol
@@ -0,0 +1,13 @@
+contract C {
+ function f() public view returns (uint) {
+ return block.blobbasefee;
+ }
+ function g() public view returns (uint ret) {
+ assembly {
+ ret := blobbasefee()
+ }
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
diff --git a/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol
new file mode 100644
index 000000000000..11a5bd991ae4
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/magic_block_blobbasefee_error.sol
@@ -0,0 +1,16 @@
+contract C {
+ function f() public view returns (uint) {
+ return block.blobbasefee;
+ }
+ function g() public view returns (uint ret) {
+ assembly {
+ ret := blobbasefee()
+ }
+ }
+}
+// ====
+// EVMVersion: =shanghai
+// ----
+// TypeError 1006: (74-91): "blobbasefee" is not supported by the VM version.
+// DeclarationError 4619: (187-198): Function "blobbasefee" not found.
+// DeclarationError 8678: (180-200): Variable count for assignment to "ret" does not match number of values (1 vs. 0)
diff --git a/test/libsolidity/syntaxTests/viewPureChecker/blobbasefee_not_pure.sol b/test/libsolidity/syntaxTests/viewPureChecker/blobbasefee_not_pure.sol
new file mode 100644
index 000000000000..3bace4285c32
--- /dev/null
+++ b/test/libsolidity/syntaxTests/viewPureChecker/blobbasefee_not_pure.sol
@@ -0,0 +1,13 @@
+contract C {
+ function f() public pure {
+ assembly { pop(blobbasefee()) }
+ }
+ function g() public pure returns (uint) {
+ return block.blobbasefee;
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// TypeError 2527: (67-80): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
+// TypeError 2527: (151-168): 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_allowed_view_cancun.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_cancun.sol
new file mode 100644
index 000000000000..37380b965df2
--- /dev/null
+++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_allowed_view_cancun.sol
@@ -0,0 +1,10 @@
+contract C {
+ function f() public view {
+ assembly {
+ pop(blobbasefee())
+ }
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
diff --git a/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_cancun.sol b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_cancun.sol
new file mode 100644
index 000000000000..5e2265f16274
--- /dev/null
+++ b/test/libsolidity/syntaxTests/viewPureChecker/inline_assembly_instructions_disallowed_pure_cancun.sol
@@ -0,0 +1,11 @@
+contract C {
+ function f() public pure {
+ assembly {
+ pop(blobbasefee())
+ }
+ }
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// TypeError 2527: (79-92): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
diff --git a/test/libyul/yulInterpreterTests/blobbasefee.yul b/test/libyul/yulInterpreterTests/blobbasefee.yul
new file mode 100644
index 000000000000..d863b1d8265f
--- /dev/null
+++ b/test/libyul/yulInterpreterTests/blobbasefee.yul
@@ -0,0 +1,10 @@
+{
+ sstore(0, blobbasefee())
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// Trace:
+// Memory dump:
+// Storage dump:
+// 0000000000000000000000000000000000000000000000000000000000000000: 0000000000000000000000000000000000000000000000000000000000000001
diff --git a/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul b/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul
new file mode 100644
index 000000000000..42c1f2c0a680
--- /dev/null
+++ b/test/libyul/yulSyntaxTests/blobbasefee_identifier_pre_cancun.yul
@@ -0,0 +1,6 @@
+{
+ function blobbasefee() {}
+}
+// ====
+// EVMVersion: <=shanghai
+// ----
diff --git a/test/libyul/yulSyntaxTests/blobbasefee_reserved_identifier_post_cancun.yul b/test/libyul/yulSyntaxTests/blobbasefee_reserved_identifier_post_cancun.yul
new file mode 100644
index 000000000000..61fa7d7e427a
--- /dev/null
+++ b/test/libyul/yulSyntaxTests/blobbasefee_reserved_identifier_post_cancun.yul
@@ -0,0 +1,7 @@
+{
+ function blobbasefee() {}
+}
+// ====
+// EVMVersion: >=cancun
+// ----
+// ParserError 5568: (15-26): Cannot use builtin function name "blobbasefee" as identifier name.
diff --git a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp
index 79dbc554a292..015924a3b61b 100644
--- a/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp
+++ b/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp
@@ -233,6 +233,8 @@ u256 EVMInstructionInterpreter::eval(
return m_state.chainid;
case Instruction::BASEFEE:
return m_state.basefee;
+ case Instruction::BLOBBASEFEE:
+ return m_state.blobbasefee;
case Instruction::EXTCODESIZE:
return u256(keccak256(h256(arg[0]))) & 0xffffff;
case Instruction::EXTCODEHASH:
diff --git a/test/tools/yulInterpreter/Interpreter.h b/test/tools/yulInterpreter/Interpreter.h
index 26a8b2701215..66082b5b30f6 100644
--- a/test/tools/yulInterpreter/Interpreter.h
+++ b/test/tools/yulInterpreter/Interpreter.h
@@ -99,6 +99,8 @@ struct InterpreterState
u256 chainid = 0x01;
/// The minimum value of basefee: 7 wei.
u256 basefee = 0x07;
+ /// The minimum value of blobbasefee: 1 wei.
+ u256 blobbasefee = 0x01;
/// Log of changes / effects. Sholud be structured data in the future.
std::vector trace;
/// This is actually an input parameter that more or less limits the runtime.