mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adds support for the EVM version "Paris".
Deprecates `block.difficulty` and disallow `difficulty()` in inline assembly for EVM versions >= paris. The change is due to the renaming introduced by EIP-4399 (see: https://eips.ethereum.org/EIPS/eip-4399). Introduces `block.prevrandao` in Solidity and `prevrandao()` in inline assembly for EVM versions >= paris. Co-authored-by: Alex Beregszaszi <alex@rtfs.hu> Co-authored-by: Daniel <daniel@ekpyron.org> Co-authored-by: matheusaaguiar <95899911+matheusaaguiar@users.noreply.github.com> Co-authored-by: Nikola Matić <nikola.matic@ethereum.org>
This commit is contained in:
co-authored by
Alex Beregszaszi
Daniel
matheusaaguiar
Nikola Matić
parent
d70d79af4a
commit
ef6ff2f055
@@ -28,6 +28,7 @@
|
||||
#include <libsolutil/Common.h>
|
||||
#include <libsolutil/CommonData.h>
|
||||
#include <libsolutil/Numeric.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
@@ -47,11 +47,12 @@ namespace
|
||||
{
|
||||
|
||||
pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
|
||||
langutil::EVMVersion _evmVersion,
|
||||
string const& _name,
|
||||
evmasm::Instruction _instruction
|
||||
)
|
||||
{
|
||||
evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction);
|
||||
evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction, _evmVersion);
|
||||
BuiltinFunctionForEVM f;
|
||||
f.name = YulString{_name};
|
||||
f.parameters.resize(static_cast<size_t>(info.args));
|
||||
@@ -119,11 +120,19 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
|
||||
return _instr == evmasm::Instruction::BASEFEE && _evmVersion < langutil::EVMVersion::london();
|
||||
};
|
||||
|
||||
// TODO remove this in 0.9.0. We allow creating functions or identifiers in Yul with the name
|
||||
// prevrandao for VMs before paris.
|
||||
auto prevRandaoException = [&](string const& _instrName) -> bool
|
||||
{
|
||||
// Using string comparison as the opcode is the same as for "difficulty"
|
||||
return _instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris();
|
||||
};
|
||||
|
||||
set<YulString> reserved;
|
||||
for (auto const& instr: evmasm::c_instructions)
|
||||
{
|
||||
string name = toLower(instr.first);
|
||||
if (!baseFeeException(instr.second))
|
||||
if (!baseFeeException(instr.second) && !prevRandaoException(name))
|
||||
reserved.emplace(name);
|
||||
}
|
||||
reserved += vector<YulString>{
|
||||
@@ -139,6 +148,13 @@ set<YulString> createReservedIdentifiers(langutil::EVMVersion _evmVersion)
|
||||
|
||||
map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVersion, bool _objectAccess)
|
||||
{
|
||||
|
||||
// Exclude prevrandao as builtin for VMs before paris and difficulty for VMs after paris.
|
||||
auto prevRandaoException = [&](string const& _instrName) -> bool
|
||||
{
|
||||
return (_instrName == "prevrandao" && _evmVersion < langutil::EVMVersion::paris()) || (_instrName == "difficulty" && _evmVersion >= langutil::EVMVersion::paris());
|
||||
};
|
||||
|
||||
map<YulString, BuiltinFunctionForEVM> builtins;
|
||||
for (auto const& instr: evmasm::c_instructions)
|
||||
{
|
||||
@@ -152,9 +168,10 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
||||
opcode != evmasm::Instruction::JUMP &&
|
||||
opcode != evmasm::Instruction::JUMPI &&
|
||||
opcode != evmasm::Instruction::JUMPDEST &&
|
||||
_evmVersion.hasOpcode(opcode)
|
||||
_evmVersion.hasOpcode(opcode) &&
|
||||
!prevRandaoException(name)
|
||||
)
|
||||
builtins.emplace(createEVMFunction(name, opcode));
|
||||
builtins.emplace(createEVMFunction(_evmVersion, name, opcode));
|
||||
}
|
||||
|
||||
if (_objectAccess)
|
||||
|
||||
@@ -88,7 +88,7 @@ void GasMeterVisitor::operator()(FunctionCall const& _funCall)
|
||||
|
||||
void GasMeterVisitor::operator()(Literal const& _lit)
|
||||
{
|
||||
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1);
|
||||
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1, m_dialect.evmVersion());
|
||||
m_dataGas +=
|
||||
singleByteDataGas() +
|
||||
evmasm::GasMeter::dataGas(
|
||||
@@ -100,7 +100,7 @@ void GasMeterVisitor::operator()(Literal const& _lit)
|
||||
|
||||
void GasMeterVisitor::operator()(Identifier const&)
|
||||
{
|
||||
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1);
|
||||
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::DUP1, m_dialect.evmVersion());
|
||||
m_dataGas += singleByteDataGas();
|
||||
}
|
||||
|
||||
@@ -120,6 +120,6 @@ void GasMeterVisitor::instructionCostsInternal(evmasm::Instruction _instruction)
|
||||
// Assumes that Keccak-256 is computed on a single word (rounded up).
|
||||
m_runGas += evmasm::GasCosts::keccak256Gas + evmasm::GasCosts::keccak256WordGas;
|
||||
else
|
||||
m_runGas += evmasm::GasMeter::runGas(_instruction);
|
||||
m_runGas += evmasm::GasMeter::runGas(_instruction, m_dialect.evmVersion());
|
||||
m_dataGas += singleByteDataGas();
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ void EthAssemblyAdapter::appendAssemblySize()
|
||||
|
||||
pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::createSubAssembly(bool _creation, string _name)
|
||||
{
|
||||
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(_creation, std::move(_name))};
|
||||
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>(m_assembly.evmVersion(), _creation, std::move(_name))};
|
||||
auto sub = m_assembly.newSub(assembly);
|
||||
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ using namespace solidity::langutil;
|
||||
|
||||
void NoOutputAssembly::appendInstruction(evmasm::Instruction _instr)
|
||||
{
|
||||
m_stackHeight += instructionInfo(_instr).ret - instructionInfo(_instr).args;
|
||||
m_stackHeight += instructionInfo(_instr, m_evmVersion).ret - instructionInfo(_instr, m_evmVersion).args;
|
||||
}
|
||||
|
||||
void NoOutputAssembly::appendConstant(u256 const&)
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace solidity::yul
|
||||
class NoOutputAssembly: public AbstractAssembly
|
||||
{
|
||||
public:
|
||||
explicit NoOutputAssembly() { }
|
||||
explicit NoOutputAssembly(langutil::EVMVersion _evmVersion): m_evmVersion(_evmVersion) { }
|
||||
~NoOutputAssembly() override = default;
|
||||
|
||||
void setSourceLocation(langutil::SourceLocation const&) override {}
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
|
||||
private:
|
||||
int m_stackHeight = 0;
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -747,23 +747,23 @@ void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::Functi
|
||||
if (_swapDepth > 16)
|
||||
opGas += 1000;
|
||||
else
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth));
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::swapInstruction(_swapDepth), langutil::EVMVersion());
|
||||
};
|
||||
auto dupOrPush = [&](StackSlot const& _slot)
|
||||
{
|
||||
if (canBeFreelyGenerated(_slot))
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32));
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), langutil::EVMVersion());
|
||||
else
|
||||
{
|
||||
auto depth = util::findOffset(_source | ranges::views::reverse, _slot);
|
||||
yulAssert(depth);
|
||||
if (*depth < 16)
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast<unsigned>(*depth + 1)));
|
||||
opGas += evmasm::GasMeter::runGas(evmasm::dupInstruction(static_cast<unsigned>(*depth + 1)), langutil::EVMVersion());
|
||||
else
|
||||
opGas += 1000;
|
||||
}
|
||||
};
|
||||
auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP); };
|
||||
auto pop = [&]() { opGas += evmasm::GasMeter::runGas(evmasm::Instruction::POP,langutil::EVMVersion()); };
|
||||
createStackLayout(_source, _target, swap, dupOrPush, pop);
|
||||
return opGas;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user