mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
wipAdd VM Version Paris and new built in function `prevrandao
Add VM Version Paris and new built in function
prevrandao
`
This commit is contained in:
parent
70b0fb6366
commit
2dc5435c19
@ -31,7 +31,7 @@ REPODIR="$(realpath "$(dirname "$0")"/..)"
|
|||||||
# shellcheck source=scripts/common.sh
|
# shellcheck source=scripts/common.sh
|
||||||
source "${REPODIR}/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
|
DEFAULT_EVM=london
|
||||||
[[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]]
|
[[ " ${EVM_VALUES[*]} " =~ $DEFAULT_EVM ]]
|
||||||
OPTIMIZE_VALUES=(0 1)
|
OPTIMIZE_VALUES=(0 1)
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
### 0.8.18 (unreleased)
|
### 0.8.18 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
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:
|
Compiler Features:
|
||||||
* Commandline Interface: Add `--no-cbor-metadata` that skips CBOR metadata from getting appended at the end of the bytecode.
|
* 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.
|
* 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.
|
* Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string.
|
||||||
|
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
@ -8,7 +8,7 @@ Order of Precedence of Operators
|
|||||||
================================
|
================================
|
||||||
.. include:: types/operator-precedence-table.rst
|
.. 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
|
Global Variables
|
||||||
================
|
================
|
||||||
@ -33,6 +33,7 @@ Global Variables
|
|||||||
- ``block.chainid`` (``uint``): current chain id
|
- ``block.chainid`` (``uint``): current chain id
|
||||||
- ``block.coinbase`` (``address payable``): current block miner's address
|
- ``block.coinbase`` (``address payable``): current block miner's address
|
||||||
- ``block.difficulty`` (``uint``): current block difficulty
|
- ``block.difficulty`` (``uint``): current block difficulty
|
||||||
|
- ``block.prevrandao`` (``uint``): randomness provided by the beacon chain
|
||||||
- ``block.gaslimit`` (``uint``): current block gaslimit
|
- ``block.gaslimit`` (``uint``): current block gaslimit
|
||||||
- ``block.number`` (``uint``): current block number
|
- ``block.number`` (``uint``): current block number
|
||||||
- ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch
|
- ``block.timestamp`` (``uint``): current block timestamp in seconds since Unix epoch
|
||||||
|
@ -291,8 +291,8 @@ YulEVMBuiltin:
|
|||||||
| 'returndatacopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode'
|
| 'returndatacopy' | 'extcodehash' | 'create' | 'create2' | 'call' | 'callcode'
|
||||||
| 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid'
|
| 'delegatecall' | 'staticcall' | 'return' | 'revert' | 'selfdestruct' | 'invalid'
|
||||||
| 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice'
|
| 'log0' | 'log1' | 'log2' | 'log3' | 'log4' | 'chainid' | 'origin' | 'gasprice'
|
||||||
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'gaslimit'
|
| 'blockhash' | 'coinbase' | 'timestamp' | 'number' | 'difficulty' | 'prevrandao'
|
||||||
| 'basefee';
|
| 'gaslimit' | 'basefee';
|
||||||
|
|
||||||
YulLBrace: '{' -> pushMode(YulMode);
|
YulLBrace: '{' -> pushMode(YulMode);
|
||||||
YulRBrace: '}' -> popMode;
|
YulRBrace: '}' -> popMode;
|
||||||
|
@ -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
|
namespace and are mainly used to provide information about the blockchain
|
||||||
or are general-use utility functions.
|
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
|
Block and Transaction Properties
|
||||||
@ -76,6 +76,7 @@ Block and Transaction Properties
|
|||||||
- ``block.chainid`` (``uint``): current chain id
|
- ``block.chainid`` (``uint``): current chain id
|
||||||
- ``block.coinbase`` (``address payable``): current block miner's address
|
- ``block.coinbase`` (``address payable``): current block miner's address
|
||||||
- ``block.difficulty`` (``uint``): current block difficulty
|
- ``block.difficulty`` (``uint``): current block difficulty
|
||||||
|
- ``block.prevrandao`` (``uint``): randomness provided by the beacon chain
|
||||||
- ``block.gaslimit`` (``uint``): current block gaslimit
|
- ``block.gaslimit`` (``uint``): current block gaslimit
|
||||||
- ``block.number`` (``uint``): current block number
|
- ``block.number`` (``uint``): current block number
|
||||||
- ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch
|
- ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch
|
||||||
|
@ -172,6 +172,9 @@ at each version. Backward compatibility is not guaranteed between each version.
|
|||||||
the optimizer.
|
the optimizer.
|
||||||
- ``london`` (**default**)
|
- ``london`` (**default**)
|
||||||
- The block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/eip-1559>`_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly.
|
- The block's base fee (`EIP-3198 <https://eips.ethereum.org/EIPS/eip-3198>`_ and `EIP-1559 <https://eips.ethereum.org/EIPS/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 <https://eips.ethereum.org/EIPS/eip-4399>`_).
|
||||||
|
Both can be used interchangeably. ``prevrandao`` is a reserved keyword in yul code.
|
||||||
|
|
||||||
|
|
||||||
.. index:: ! standard JSON, ! --standard-json
|
.. index:: ! standard JSON, ! --standard-json
|
||||||
|
10
docs/yul.rst
10
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.
|
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 ``-`` 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,
|
Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L`` and ``P`` are present since Frontier, Homestead,
|
||||||
Byzantium, Constantinople, Istanbul or London respectively.
|
Byzantium, Constantinople, Istanbul, London or Paris respectively.
|
||||||
|
|
||||||
In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to
|
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``.
|
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 |
|
| 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 |
|
| gaslimit() | | F | block gas limit of the current block |
|
||||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||||
|
@ -77,6 +77,7 @@ std::map<std::string, Instruction> const solidity::evmasm::c_instructions =
|
|||||||
{ "TIMESTAMP", Instruction::TIMESTAMP },
|
{ "TIMESTAMP", Instruction::TIMESTAMP },
|
||||||
{ "NUMBER", Instruction::NUMBER },
|
{ "NUMBER", Instruction::NUMBER },
|
||||||
{ "DIFFICULTY", Instruction::DIFFICULTY },
|
{ "DIFFICULTY", Instruction::DIFFICULTY },
|
||||||
|
{ "PREVRANDAO", Instruction::PREVRANDAO },
|
||||||
{ "GASLIMIT", Instruction::GASLIMIT },
|
{ "GASLIMIT", Instruction::GASLIMIT },
|
||||||
{ "CHAINID", Instruction::CHAINID },
|
{ "CHAINID", Instruction::CHAINID },
|
||||||
{ "SELFBALANCE", Instruction::SELFBALANCE },
|
{ "SELFBALANCE", Instruction::SELFBALANCE },
|
||||||
@ -223,6 +224,8 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
|
|||||||
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::COINBASE, { "COINBASE", 0, 0, 1, false, Tier::Base } },
|
||||||
{ Instruction::TIMESTAMP, { "TIMESTAMP", 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::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::DIFFICULTY, { "DIFFICULTY", 0, 0, 1, false, Tier::Base } },
|
||||||
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::GASLIMIT, { "GASLIMIT", 0, 0, 1, false, Tier::Base } },
|
||||||
{ Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } },
|
{ Instruction::CHAINID, { "CHAINID", 0, 0, 1, false, Tier::Base } },
|
||||||
|
@ -84,7 +84,8 @@ enum class Instruction: uint8_t
|
|||||||
TIMESTAMP, ///< get the block's timestamp
|
TIMESTAMP, ///< get the block's timestamp
|
||||||
NUMBER, ///< get the block's number
|
NUMBER, ///< get the block's number
|
||||||
DIFFICULTY, ///< get the block's difficulty
|
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
|
CHAINID, ///< get the config's chainid param
|
||||||
SELFBALANCE, ///< get balance of the current account
|
SELFBALANCE, ///< get balance of the current account
|
||||||
BASEFEE, ///< get the block's basefee
|
BASEFEE, ///< get the block's basefee
|
||||||
|
@ -123,6 +123,7 @@ struct EVMBuiltins
|
|||||||
static auto constexpr TIMESTAMP = PatternGenerator<Instruction::TIMESTAMP>{};
|
static auto constexpr TIMESTAMP = PatternGenerator<Instruction::TIMESTAMP>{};
|
||||||
static auto constexpr NUMBER = PatternGenerator<Instruction::NUMBER>{};
|
static auto constexpr NUMBER = PatternGenerator<Instruction::NUMBER>{};
|
||||||
static auto constexpr DIFFICULTY = PatternGenerator<Instruction::DIFFICULTY>{};
|
static auto constexpr DIFFICULTY = PatternGenerator<Instruction::DIFFICULTY>{};
|
||||||
|
static auto constexpr PREVRANDAO = PatternGenerator<Instruction::PREVRANDAO>{};
|
||||||
static auto constexpr GASLIMIT = PatternGenerator<Instruction::GASLIMIT>{};
|
static auto constexpr GASLIMIT = PatternGenerator<Instruction::GASLIMIT>{};
|
||||||
static auto constexpr CHAINID = PatternGenerator<Instruction::CHAINID>{};
|
static auto constexpr CHAINID = PatternGenerator<Instruction::CHAINID>{};
|
||||||
static auto constexpr SELFBALANCE = PatternGenerator<Instruction::SELFBALANCE>{};
|
static auto constexpr SELFBALANCE = PatternGenerator<Instruction::SELFBALANCE>{};
|
||||||
|
@ -52,10 +52,11 @@ public:
|
|||||||
static EVMVersion istanbul() { return {Version::Istanbul}; }
|
static EVMVersion istanbul() { return {Version::Istanbul}; }
|
||||||
static EVMVersion berlin() { return {Version::Berlin}; }
|
static EVMVersion berlin() { return {Version::Berlin}; }
|
||||||
static EVMVersion london() { return {Version::London}; }
|
static EVMVersion london() { return {Version::London}; }
|
||||||
|
static EVMVersion paris() { return {Version::Paris}; }
|
||||||
|
|
||||||
static std::optional<EVMVersion> fromString(std::string const& _version)
|
static std::optional<EVMVersion> 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())
|
if (_version == v.name())
|
||||||
return v;
|
return v;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@ -77,6 +78,7 @@ public:
|
|||||||
case Version::Istanbul: return "istanbul";
|
case Version::Istanbul: return "istanbul";
|
||||||
case Version::Berlin: return "berlin";
|
case Version::Berlin: return "berlin";
|
||||||
case Version::London: return "london";
|
case Version::London: return "london";
|
||||||
|
case Version::Paris: return "paris";
|
||||||
}
|
}
|
||||||
return "INVALID";
|
return "INVALID";
|
||||||
}
|
}
|
||||||
@ -90,6 +92,8 @@ public:
|
|||||||
bool hasChainID() const { return *this >= istanbul(); }
|
bool hasChainID() const { return *this >= istanbul(); }
|
||||||
bool hasSelfBalance() const { return *this >= istanbul(); }
|
bool hasSelfBalance() const { return *this >= istanbul(); }
|
||||||
bool hasBaseFee() const { return *this >= london(); }
|
bool hasBaseFee() const { return *this >= london(); }
|
||||||
|
bool hasPrevRandao() const { return *this >= paris(); }
|
||||||
|
bool hasDifficulty() const { return *this < paris(); }
|
||||||
|
|
||||||
bool hasOpcode(evmasm::Instruction _opcode) const;
|
bool hasOpcode(evmasm::Instruction _opcode) const;
|
||||||
|
|
||||||
@ -98,11 +102,11 @@ public:
|
|||||||
bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
|
bool canOverchargeGasForCall() const { return *this >= tangerineWhistle(); }
|
||||||
|
|
||||||
private:
|
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) {}
|
EVMVersion(Version _version): m_version(_version) {}
|
||||||
|
|
||||||
Version m_version = Version::London;
|
Version m_version = Version::Paris;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3286,18 +3286,33 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
|
|||||||
(memberName == "min" || memberName == "max")
|
(memberName == "min" || memberName == "max")
|
||||||
)
|
)
|
||||||
annotation.isPure = true;
|
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(
|
m_errorReporter.typeError(
|
||||||
3081_error,
|
3081_error,
|
||||||
_memberAccess.location(),
|
_memberAccess.location(),
|
||||||
"\"chainid\" is not supported by the VM version."
|
"\"chainid\" is not supported by the VM version."
|
||||||
);
|
);
|
||||||
else if (magicType->kind() == MagicType::Kind::Block && memberName == "basefee" && !m_evmVersion.hasBaseFee())
|
else if (memberName == "basefee" && !m_evmVersion.hasBaseFee())
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
5921_error,
|
5921_error,
|
||||||
_memberAccess.location(),
|
_memberAccess.location(),
|
||||||
"\"basefee\" is not supported by the VM version."
|
"\"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 (
|
if (
|
||||||
|
@ -4059,6 +4059,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
|
|||||||
{"timestamp", TypeProvider::uint256()},
|
{"timestamp", TypeProvider::uint256()},
|
||||||
{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)},
|
{"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)},
|
||||||
{"difficulty", TypeProvider::uint256()},
|
{"difficulty", TypeProvider::uint256()},
|
||||||
|
{"prevrandao", TypeProvider::uint256()},
|
||||||
{"number", TypeProvider::uint256()},
|
{"number", TypeProvider::uint256()},
|
||||||
{"gaslimit", TypeProvider::uint256()},
|
{"gaslimit", TypeProvider::uint256()},
|
||||||
{"chainid", TypeProvider::uint256()},
|
{"chainid", TypeProvider::uint256()},
|
||||||
|
@ -1810,6 +1810,8 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
|||||||
m_context << Instruction::TIMESTAMP;
|
m_context << Instruction::TIMESTAMP;
|
||||||
else if (member == "difficulty")
|
else if (member == "difficulty")
|
||||||
m_context << Instruction::DIFFICULTY;
|
m_context << Instruction::DIFFICULTY;
|
||||||
|
else if (member == "prevrandao")
|
||||||
|
m_context << Instruction::PREVRANDAO;
|
||||||
else if (member == "number")
|
else if (member == "number")
|
||||||
m_context << Instruction::NUMBER;
|
m_context << Instruction::NUMBER;
|
||||||
else if (member == "gaslimit")
|
else if (member == "gaslimit")
|
||||||
|
@ -1822,8 +1822,13 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
define(_memberAccess) << "coinbase()\n";
|
define(_memberAccess) << "coinbase()\n";
|
||||||
else if (member == "timestamp")
|
else if (member == "timestamp")
|
||||||
define(_memberAccess) << "timestamp()\n";
|
define(_memberAccess) << "timestamp()\n";
|
||||||
else if (member == "difficulty")
|
else if (member == "difficulty" || member == "prevrandao")
|
||||||
|
{
|
||||||
|
if (m_context.evmVersion().hasPrevRandao())
|
||||||
|
define(_memberAccess) << "prevrandao()\n";
|
||||||
|
else
|
||||||
define(_memberAccess) << "difficulty()\n";
|
define(_memberAccess) << "difficulty()\n";
|
||||||
|
}
|
||||||
else if (member == "number")
|
else if (member == "number")
|
||||||
define(_memberAccess) << "number()\n";
|
define(_memberAccess) << "number()\n";
|
||||||
else if (member == "gaslimit")
|
else if (member == "gaslimit")
|
||||||
|
@ -118,12 +118,19 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
|
|||||||
{
|
{
|
||||||
return _instr == evmasm::Instruction::BASEFEE && _evmVersion < langutil::EVMVersion::london();
|
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<YulString> reserved;
|
set<YulString> reserved;
|
||||||
for (auto const& instr: evmasm::c_instructions)
|
for (auto const& instr: evmasm::c_instructions)
|
||||||
{
|
{
|
||||||
string name = toLower(instr.first);
|
string name = toLower(instr.first);
|
||||||
if (!baseFeeException(instr.second))
|
if (!baseFeeException(instr.second) && !prevRandAOException(name))
|
||||||
reserved.emplace(name);
|
reserved.emplace(name);
|
||||||
}
|
}
|
||||||
reserved += vector<YulString>{
|
reserved += vector<YulString>{
|
||||||
@ -139,6 +146,17 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
|
|||||||
|
|
||||||
map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess)
|
map<YulString, BuiltinFunctionForEVM> 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<YulString, BuiltinFunctionForEVM> builtins;
|
map<YulString, BuiltinFunctionForEVM> builtins;
|
||||||
for (auto const& instr: evmasm::c_instructions)
|
for (auto const& instr: evmasm::c_instructions)
|
||||||
{
|
{
|
||||||
@ -152,7 +170,7 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
opcode != evmasm::Instruction::JUMP &&
|
opcode != evmasm::Instruction::JUMP &&
|
||||||
opcode != evmasm::Instruction::JUMPI &&
|
opcode != evmasm::Instruction::JUMPI &&
|
||||||
opcode != evmasm::Instruction::JUMPDEST &&
|
opcode != evmasm::Instruction::JUMPDEST &&
|
||||||
_evmVersion.hasOpcode(opcode)
|
hasOpCode(opcode, name)
|
||||||
)
|
)
|
||||||
builtins.emplace(createEVMFunction(name, opcode));
|
builtins.emplace(createEVMFunction(name, opcode));
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,9 @@ done < <(
|
|||||||
grep -v -E 'revertStatement/non_called.sol' |
|
grep -v -E 'revertStatement/non_called.sol' |
|
||||||
# Skipping a test with "let basefee := ..."
|
# Skipping a test with "let basefee := ..."
|
||||||
grep -v -E 'inlineAssembly/basefee_berlin_function.sol' |
|
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
|
# Skipping license error, unrelated to the grammar
|
||||||
grep -v -E 'license/license_double5.sol' |
|
grep -v -E 'license/license_double5.sol' |
|
||||||
grep -v -E 'license/license_hidden_unicode.sol' |
|
grep -v -E 'license/license_hidden_unicode.sol' |
|
||||||
|
@ -122,6 +122,8 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
|
|||||||
m_evmRevision = EVMC_BERLIN;
|
m_evmRevision = EVMC_BERLIN;
|
||||||
else if (_evmVersion == langutil::EVMVersion::london())
|
else if (_evmVersion == langutil::EVMVersion::london())
|
||||||
m_evmRevision = EVMC_LONDON;
|
m_evmRevision = EVMC_LONDON;
|
||||||
|
else if (_evmVersion == langutil::EVMVersion::paris())
|
||||||
|
m_evmRevision = EVMC_PARIS;
|
||||||
else
|
else
|
||||||
assertThrow(false, Exception, "Unsupported EVM version");
|
assertThrow(false, Exception, "Unsupported EVM version");
|
||||||
|
|
||||||
|
@ -832,12 +832,19 @@ enum evmc_revision
|
|||||||
*/
|
*/
|
||||||
EVMC_LONDON = 9,
|
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.
|
* The Shanghai revision.
|
||||||
*
|
*
|
||||||
* https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md
|
* 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. */
|
/** The maximum EVM revision supported. */
|
||||||
EVMC_MAX_REVISION = EVMC_SHANGHAI,
|
EVMC_MAX_REVISION = EVMC_SHANGHAI,
|
||||||
|
@ -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: <paris
|
||||||
|
// ----
|
||||||
|
// f() -> 0
|
||||||
|
// g() -> 1000
|
@ -0,0 +1,6 @@
|
|||||||
|
function f() view returns (uint) {
|
||||||
|
return block.difficulty;
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: <paris
|
||||||
|
// ----
|
@ -0,0 +1,18 @@
|
|||||||
|
contract C {
|
||||||
|
function f() public view returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
let difficulty := sload(0)
|
||||||
|
ret := difficulty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function g() public pure returns (uint ret) {
|
||||||
|
assembly {
|
||||||
|
function difficulty() -> r {
|
||||||
|
r := 1000
|
||||||
|
}
|
||||||
|
ret := difficulty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// ParserError 5568: (98-108): Cannot use builtin function name "difficulty" as identifier name.
|
@ -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.
|
@ -0,0 +1,6 @@
|
|||||||
|
function f() view returns (uint) {
|
||||||
|
return block.prevrandao;
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: >=paris
|
||||||
|
// ----
|
@ -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.
|
@ -0,0 +1,7 @@
|
|||||||
|
function f() view returns (uint) {
|
||||||
|
return block.prevrandao;
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// EVMVersion: <paris
|
||||||
|
// ----
|
||||||
|
// Warning 9432: (43-59): "prevrandao" is not supported by the VM version and will be treated like "difficulty".
|
@ -2,9 +2,6 @@ contract C {
|
|||||||
function f() public view returns (address payable) {
|
function f() public view returns (address payable) {
|
||||||
return block.coinbase;
|
return block.coinbase;
|
||||||
}
|
}
|
||||||
function g() public view returns (uint) {
|
|
||||||
return block.difficulty;
|
|
||||||
}
|
|
||||||
function h() public view returns (uint) {
|
function h() public view returns (uint) {
|
||||||
return block.gaslimit;
|
return block.gaslimit;
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,7 @@ contract C {
|
|||||||
//pop(timestamp())
|
//pop(timestamp())
|
||||||
//pop(number())
|
//pop(number())
|
||||||
//pop(difficulty())
|
//pop(difficulty())
|
||||||
|
//pop(prevrandao())
|
||||||
//pop(gaslimit())
|
//pop(gaslimit())
|
||||||
|
|
||||||
// NOTE: msize() is allowed only with optimizer disabled
|
// NOTE: msize() is allowed only with optimizer disabled
|
||||||
|
@ -73,7 +73,7 @@ contract C {
|
|||||||
pop(coinbase())
|
pop(coinbase())
|
||||||
pop(timestamp())
|
pop(timestamp())
|
||||||
pop(number())
|
pop(number())
|
||||||
pop(difficulty())
|
pop(prevrandao())
|
||||||
pop(gaslimit())
|
pop(gaslimit())
|
||||||
|
|
||||||
// NOTE: msize() is allowed only with optimizer disabled
|
// NOTE: msize() is allowed only with optimizer disabled
|
||||||
@ -83,7 +83,7 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// EVMVersion: >=london
|
// EVMVersion: >=paris
|
||||||
// ----
|
// ----
|
||||||
// Warning 5740: (94-1733): Unreachable code.
|
// Warning 5740: (94-1733): Unreachable code.
|
||||||
// Warning 5740: (1746-1758): Unreachable code.
|
// Warning 5740: (1746-1758): Unreachable code.
|
||||||
|
@ -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.
|
@ -32,7 +32,7 @@ contract C {
|
|||||||
pop(coinbase())
|
pop(coinbase())
|
||||||
pop(timestamp())
|
pop(timestamp())
|
||||||
pop(number())
|
pop(number())
|
||||||
pop(difficulty())
|
pop(prevrandao())
|
||||||
pop(gaslimit())
|
pop(gaslimit())
|
||||||
|
|
||||||
// These two are disallowed too but the error suppresses other errors.
|
// 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.
|
// 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 2527: (79-87): Function declared as pure, but this expression (potentially) reads from the environment or state and thus requires "view".
|
||||||
|
@ -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".
|
Loading…
Reference in New Issue
Block a user