Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/soltest_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ set -e

REPODIR="$(realpath "$(dirname "$0")"/..)"

EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin)
EVM_VALUES=(homestead byzantium constantinople petersburg istanbul berlin london)
DEFAULT_EVM=berlin
[[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]]
OPTIMIZE_VALUES=(0 1)
Expand Down
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
### 0.8.7 (unreleased)

Language Features:
* Introduce global ``block.basefee`` for retrieving the base fee of the current block.
* Yul: Introduce builtin ``basefee()`` for retrieving the base fee of the current block.


Compiler Features:
Expand Down
1 change: 1 addition & 0 deletions docs/cheatsheet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Global Variables
to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)```
- ``bytes.concat(...) returns (bytes memory)``: :ref:`Concatenates variable number of
arguments to one byte array<bytes-concat>`
- ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
- ``block.chainid`` (``uint``): current chain id
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty
Expand Down
3 changes: 2 additions & 1 deletion docs/grammar/SolidityLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,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';
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'gaslimit'
| 'basefee';

YulLBrace: '{' -> pushMode(YulMode);
YulRBrace: '}' -> popMode;
Expand Down
1 change: 1 addition & 0 deletions docs/units-and-global-variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,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 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_)
- ``block.chainid`` (``uint``): current chain id
- ``block.coinbase`` (``address payable``): current block miner's address
- ``block.difficulty`` (``uint``): current block difficulty
Expand Down
8 changes: 5 additions & 3 deletions docs/yul.rst
Original file line number Diff line number Diff line change
Expand Up @@ -717,8 +717,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`` or ``I`` are present since Frontier, Homestead,
Byzantium, Constantinople or Istanbul, respectively.
Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I`` and ``L`` are present since Frontier, Homestead,
Byzantium, Constantinople, Istanbul or London 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``.
Expand Down Expand Up @@ -879,7 +879,9 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a
| log4(p, s, t1, t2, t3, | `-` | F | log with topics t1, t2, t3, t4 and data mem[p...(p+s)) |
| t4) | | | |
+-------------------------+-----+---+-----------------------------------------------------------------+
| chainid() | | I | ID of the executing chain (EIP 1344) |
| chainid() | | I | ID of the executing chain (EIP-1344) |
+-------------------------+-----+---+-----------------------------------------------------------------+
| basefee() | | L | current block's base fee (EIP-3198 and EIP-1559) |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc on the top also explains what these letters stand for, L is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Fixed.

+-------------------------+-----+---+-----------------------------------------------------------------+
| origin() | | F | transaction sender |
+-------------------------+-----+---+-----------------------------------------------------------------+
Expand Down
2 changes: 2 additions & 0 deletions libevmasm/Instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ std::map<std::string, Instruction> const solidity::evmasm::c_instructions =
{ "GASLIMIT", Instruction::GASLIMIT },
{ "CHAINID", Instruction::CHAINID },
{ "SELFBALANCE", Instruction::SELFBALANCE },
{ "BASEFEE", Instruction::BASEFEE },
{ "POP", Instruction::POP },
{ "MLOAD", Instruction::MLOAD },
{ "MSTORE", Instruction::MSTORE },
Expand Down Expand Up @@ -230,6 +231,7 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } },
{ 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::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 } },
Expand Down
1 change: 1 addition & 0 deletions libevmasm/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ enum class Instruction: uint8_t
GASLIMIT, ///< 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

POP = 0x50, ///< remove item from stack
MLOAD, ///< load word from memory
Expand Down
1 change: 1 addition & 0 deletions libevmasm/SemanticInformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
case Instruction::CALLER:
case Instruction::CALLVALUE:
case Instruction::CHAINID:
case Instruction::BASEFEE:
case Instruction::GAS:
case Instruction::GASPRICE:
case Instruction::EXTCODESIZE:
Expand Down
7 changes: 5 additions & 2 deletions liblangutil/EVMVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ class EVMVersion:
static EVMVersion petersburg() { return {Version::Petersburg}; }
static EVMVersion istanbul() { return {Version::Istanbul}; }
static EVMVersion berlin() { return {Version::Berlin}; }
static EVMVersion london() { return {Version::London}; }

static std::optional<EVMVersion> fromString(std::string const& _version)
{
for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin()})
for (auto const& v: {homestead(), tangerineWhistle(), spuriousDragon(), byzantium(), constantinople(), petersburg(), istanbul(), berlin(), london()})
if (_version == v.name())
return v;
return std::nullopt;
Expand All @@ -75,6 +76,7 @@ class EVMVersion:
case Version::Petersburg: return "petersburg";
case Version::Istanbul: return "istanbul";
case Version::Berlin: return "berlin";
case Version::London: return "london";
}
return "INVALID";
}
Expand All @@ -87,6 +89,7 @@ class EVMVersion:
bool hasExtCodeHash() const { return *this >= constantinople(); }
bool hasChainID() const { return *this >= istanbul(); }
bool hasSelfBalance() const { return *this >= istanbul(); }
bool hasBaseFee() const { return *this >= london(); }

bool hasOpcode(evmasm::Instruction _opcode) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done in 0c8b612

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or second commit in #11763


Expand All @@ -95,7 +98,7 @@ class EVMVersion:
bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }

private:
enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin };
enum class Version { Homestead, TangerineWhistle, SpuriousDragon, Byzantium, Constantinople, Petersburg, Istanbul, Berlin, London };

EVMVersion(Version _version): m_version(_version) {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make a separate PR changing the default to London.

Expand Down
6 changes: 6 additions & 0 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2947,6 +2947,12 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
_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."
);
}

if (
Expand Down
3 changes: 2 additions & 1 deletion libsolidity/ast/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3892,7 +3892,8 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
{"difficulty", TypeProvider::uint256()},
{"number", TypeProvider::uint256()},
{"gaslimit", TypeProvider::uint256()},
{"chainid", TypeProvider::uint256()}
{"chainid", TypeProvider::uint256()},
{"basefee", TypeProvider::uint256()}
});
case Kind::Message:
return MemberList::MemberMap({
Expand Down
2 changes: 2 additions & 0 deletions libsolidity/codegen/ExpressionCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
m_context << Instruction::GASPRICE;
else if (member == "chainid")
m_context << Instruction::CHAINID;
else if (member == "basefee")
m_context << Instruction::BASEFEE;
else if (member == "data")
m_context << u256(0) << Instruction::CALLDATASIZE;
else if (member == "sig")
Expand Down
2 changes: 2 additions & 0 deletions libsolidity/codegen/ir/IRGeneratorForStatements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1733,6 +1733,8 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
define(_memberAccess) << "gasprice()\n";
else if (member == "chainid")
define(_memberAccess) << "chainid()\n";
else if (member == "basefee")
define(_memberAccess) << "basefee()\n";
else if (member == "data")
{
IRVariable var(_memberAccess);
Expand Down
2 changes: 2 additions & 0 deletions libyul/AsmAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,8 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
errorForVM(1561_error, "only available for Istanbul-compatible");
else if (_instr == evmasm::Instruction::SELFBALANCE && !m_evmVersion.hasSelfBalance())
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::PC)
m_errorReporter.error(
2450_error,
Expand Down
4 changes: 4 additions & 0 deletions test/EVMHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
m_evmRevision = EVMC_ISTANBUL;
else if (_evmVersion == langutil::EVMVersion::berlin())
m_evmRevision = EVMC_BERLIN;
else if (_evmVersion == langutil::EVMVersion::london())
m_evmRevision = EVMC_LONDON;
else
assertThrow(false, Exception, "Unsupported EVM version");

Expand All @@ -132,6 +134,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
tx_context.tx_origin = 0x9292929292929292929292929292929292929292_address;
// Mainnet according to EIP-155
tx_context.chain_id = evmc::uint256be{1};
// The minimum value of basefee
tx_context.block_base_fee = evmc::bytes32{7};

// Reserve space for recording calls.
if (!recorded_calls.capacity())
Expand Down
18 changes: 18 additions & 0 deletions test/libsolidity/semanticTests/state/block_basefee.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
contract C {
function f() public view returns (uint) {
return block.basefee;
}
function g() public view returns (uint ret) {
assembly {
ret := basefee()
}
}
}
// ====
// EVMVersion: >=london
// compileViaYul: also
// ----
// f() -> 7
// g() -> 7
// f() -> 7
// g() -> 7
15 changes: 15 additions & 0 deletions test/libsolidity/syntaxTests/types/magic_block_basefee_error.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
contract C {
function f() public view returns (uint) {
return block.basefee;
}
function g() public view returns (uint ret) {
assembly {
ret := basefee()
}
}
}
// ====
// 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").
13 changes: 13 additions & 0 deletions test/libsolidity/syntaxTests/types/magic_block_london.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
contract C {
function f() public view returns (uint) {
return block.basefee;
}
function g() public view returns (uint ret) {
assembly {
ret := basefee()
}
}
}
// ====
// EVMVersion: >=london
// ----
13 changes: 13 additions & 0 deletions test/libsolidity/syntaxTests/viewPureChecker/basefee_not_pure.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
contract C {
function f() public pure {
assembly { pop(basefee()) }
}
function g() public pure returns (uint) {
return block.basefee;
}
}
// ====
// EVMVersion: >=london
// ----
// TypeError 2527: (67-76): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
// TypeError 2527: (147-160): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
2 changes: 1 addition & 1 deletion test/libyul/objectCompiler/dataoffset_data.yul
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ object "a" {
// stop
// data_acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f 48656c6c6f2c20576f726c6421
// Bytecode: 6006600055fe48656c6c6f2c20576f726c6421
// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID 0x48 PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000
// Opcodes: PUSH1 0x6 PUSH1 0x0 SSTORE INVALID BASEFEE PUSH6 0x6C6C6F2C2057 PUSH16 0x726C6421000000000000000000000000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:)

// SourceMappings: 32:19:0:-:0;29:1;22:30
2 changes: 2 additions & 0 deletions test/tools/yulInterpreter/EVMInstructionInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ u256 EVMInstructionInterpreter::eval(
return m_state.gasprice;
case Instruction::CHAINID:
return m_state.chainid;
case Instruction::BASEFEE:
return m_state.basefee;
case Instruction::EXTCODESIZE:
return u256(keccak256(h256(arg[0]))) & 0xffffff;
case Instruction::EXTCODEHASH:
Expand Down
3 changes: 2 additions & 1 deletion test/tools/yulInterpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ struct InterpreterState
u256 difficulty = 0x9999999;
u256 gaslimit = 4000000;
u256 chainid = 0x01;
/// The minimum value of basefee: 7 wei.
u256 basefee = 0x07;
/// Log of changes / effects. Sholud be structured data in the future.
std::vector<std::string> trace;
/// This is actually an input parameter that more or less limits the runtime.
Expand Down Expand Up @@ -227,4 +229,3 @@ class ExpressionEvaluator: public ASTWalker
};

}