Skip to content

Commit 2f4795d

Browse files
committed
eof: Introduce new instruction set for ext*call
1 parent 953a4ca commit 2f4795d

File tree

7 files changed

+85
-1
lines changed

7 files changed

+85
-1
lines changed

libevmasm/Instruction.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@ std::map<std::string, Instruction> const solidity::evmasm::c_instructions =
182182
{ "STATICCALL", Instruction::STATICCALL },
183183
{ "RETURN", Instruction::RETURN },
184184
{ "DELEGATECALL", Instruction::DELEGATECALL },
185+
{ "EXTCALL", Instruction::EXTCALL },
186+
{ "EXTSTATICCALL", Instruction::EXTSTATICCALL },
187+
{ "EXTDELEGATECALL", Instruction::EXTDELEGATECALL },
185188
{ "CREATE2", Instruction::CREATE2 },
186189
{ "REVERT", Instruction::REVERT },
187190
{ "INVALID", Instruction::INVALID },
@@ -344,6 +347,9 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
344347
{Instruction::RETURN, {"RETURN", 0, 2, 0, true, Tier::Zero}},
345348
{Instruction::DELEGATECALL, {"DELEGATECALL", 0, 6, 1, true, Tier::Special}},
346349
{Instruction::STATICCALL, {"STATICCALL", 0, 6, 1, true, Tier::Special}},
350+
{Instruction::EXTCALL, {"EXTCALL", 0, 4, 1, true, Tier::Special}},
351+
{Instruction::EXTDELEGATECALL,{"EXTDELEGATECALL", 0, 3, 1, true, Tier::Special}},
352+
{Instruction::EXTSTATICCALL, {"EXTSTATICCALL", 0, 3, 1, true, Tier::Special}},
347353
{Instruction::CREATE2, {"CREATE2", 0, 4, 1, true, Tier::Special}},
348354
{Instruction::REVERT, {"REVERT", 0, 2, 0, true, Tier::Zero}},
349355
{Instruction::INVALID, {"INVALID", 0, 0, 0, true, Tier::Zero}},

libevmasm/Instruction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,10 @@ enum class Instruction: uint8_t
198198
RETURN, ///< halt execution returning output data
199199
DELEGATECALL, ///< like CALLCODE but keeps caller's value and sender
200200
CREATE2 = 0xf5, ///< create new account with associated code at address `sha3(0xff + sender + salt + init code) % 2**160`
201+
EXTCALL = 0xf8, ///< EOF message-call into an account
202+
EXTDELEGATECALL = 0xf9, ///< EOF delegate call
201203
STATICCALL = 0xfa, ///< like CALL but disallow state modifications
204+
EXTSTATICCALL = 0xfb, ///< like EXTCALL but disallow state modifications
202205

203206
REVERT = 0xfd, ///< halt execution, revert state and return output data
204207
INVALID = 0xfe, ///< invalid instruction for expressing runtime errors (e.g., division-by-zero)
@@ -214,6 +217,9 @@ constexpr bool isCallInstruction(Instruction _inst) noexcept
214217
case Instruction::CALLCODE:
215218
case Instruction::DELEGATECALL:
216219
case Instruction::STATICCALL:
220+
case Instruction::EXTCALL:
221+
case Instruction::EXTSTATICCALL:
222+
case Instruction::EXTDELEGATECALL:
217223
return true;
218224
default:
219225
return false;

libevmasm/SemanticInformation.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,26 @@ std::vector<SemanticInformation::Operation> SemanticInformation::readWriteOperat
169169
});
170170
return operations;
171171
}
172+
case Instruction::EXTCALL:
173+
case Instruction::EXTSTATICCALL:
174+
case Instruction::EXTDELEGATECALL:
175+
{
176+
size_t paramCount = static_cast<size_t>(instructionInfo(_instruction, langutil::EVMVersion()).args);
177+
size_t const memoryStartParam = _instruction == Instruction::EXTCALL ? paramCount - 3 : paramCount - 2;
178+
size_t const memoryLengthParam = _instruction == Instruction::EXTCALL ? paramCount - 2 : paramCount - 1;
179+
std::vector<Operation> operations{
180+
Operation{Location::Memory, Effect::Read, memoryStartParam, memoryLengthParam, {}},
181+
Operation{Location::Storage, Effect::Read, {}, {}, {}},
182+
Operation{Location::TransientStorage, Effect::Read, {}, {}, {}}
183+
};
184+
if (_instruction == Instruction::EXTDELEGATECALL)
185+
{
186+
operations.emplace_back(Operation{Location::Storage, Effect::Write, {}, {}, {}});
187+
operations.emplace_back(Operation{Location::TransientStorage, Effect::Write, {}, {}, {}});
188+
}
189+
190+
return operations;
191+
}
172192
case Instruction::CREATE:
173193
case Instruction::CREATE2:
174194
return std::vector<Operation>{
@@ -380,6 +400,9 @@ bool SemanticInformation::isDeterministic(AssemblyItem const& _item)
380400
case Instruction::CALLCODE:
381401
case Instruction::DELEGATECALL:
382402
case Instruction::STATICCALL:
403+
case Instruction::EXTCALL:
404+
case Instruction::EXTDELEGATECALL:
405+
case Instruction::EXTSTATICCALL:
383406
case Instruction::CREATE:
384407
case Instruction::CREATE2:
385408
case Instruction::GAS:
@@ -475,6 +498,9 @@ SemanticInformation::Effect SemanticInformation::memory(Instruction _instruction
475498
case Instruction::LOG4:
476499
case Instruction::EOFCREATE:
477500
case Instruction::RETURNCONTRACT:
501+
case Instruction::EXTCALL:
502+
case Instruction::EXTDELEGATECALL:
503+
case Instruction::EXTSTATICCALL:
478504
return SemanticInformation::Read;
479505

480506
default:
@@ -514,10 +540,13 @@ SemanticInformation::Effect SemanticInformation::storage(Instruction _instructio
514540
case Instruction::SSTORE:
515541
case Instruction::EOFCREATE:
516542
case Instruction::RETURNCONTRACT:
543+
case Instruction::EXTCALL:
544+
case Instruction::EXTDELEGATECALL:
517545
return SemanticInformation::Write;
518546

519547
case Instruction::SLOAD:
520548
case Instruction::STATICCALL:
549+
case Instruction::EXTSTATICCALL:
521550
return SemanticInformation::Read;
522551

523552
default:
@@ -537,10 +566,13 @@ SemanticInformation::Effect SemanticInformation::transientStorage(Instruction _i
537566
case Instruction::TSTORE:
538567
case Instruction::EOFCREATE:
539568
case Instruction::RETURNCONTRACT:
569+
case Instruction::EXTCALL:
570+
case Instruction::EXTDELEGATECALL:
540571
return SemanticInformation::Write;
541572

542573
case Instruction::TLOAD:
543574
case Instruction::STATICCALL:
575+
case Instruction::EXTSTATICCALL:
544576
return SemanticInformation::Read;
545577

546578
default:
@@ -559,7 +591,10 @@ SemanticInformation::Effect SemanticInformation::otherState(Instruction _instruc
559591
case Instruction::CREATE2:
560592
case Instruction::EOFCREATE:
561593
case Instruction::RETURNCONTRACT:
594+
case Instruction::EXTCALL:
595+
case Instruction::EXTDELEGATECALL:
562596
case Instruction::SELFDESTRUCT:
597+
case Instruction::EXTSTATICCALL:
563598
case Instruction::STATICCALL: // because it can affect returndatasize
564599
// Strictly speaking, log0, .., log4 writes to the state, but the EVM cannot read it, so they
565600
// are just marked as having 'other side effects.'
@@ -606,6 +641,7 @@ bool SemanticInformation::invalidInPureFunctions(Instruction _instruction)
606641
case Instruction::NUMBER:
607642
case Instruction::PREVRANDAO:
608643
case Instruction::GASLIMIT:
644+
case Instruction::EXTSTATICCALL:
609645
case Instruction::STATICCALL:
610646
case Instruction::SLOAD:
611647
case Instruction::TLOAD:
@@ -635,6 +671,8 @@ bool SemanticInformation::invalidInViewFunctions(Instruction _instruction)
635671
case Instruction::CALL:
636672
case Instruction::CALLCODE:
637673
case Instruction::DELEGATECALL:
674+
case Instruction::EXTCALL:
675+
case Instruction::EXTDELEGATECALL:
638676
// According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#eofcreate
639677
case Instruction::EOFCREATE:
640678
// According to EOF spec https://eips.ethereum.org/EIPS/eip-7620#returncontract

liblangutil/EVMVersion.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ bool EVMVersion::hasOpcode(Instruction _opcode, std::optional<uint8_t> _eofVersi
8585
case Instruction::CALLF:
8686
case Instruction::JUMPF:
8787
case Instruction::RETF:
88+
case Instruction::EXTCALL:
89+
case Instruction::EXTSTATICCALL:
90+
case Instruction::EXTDELEGATECALL:
8891
return _eofVersion.has_value();
8992
default:
9093
return true;

libyul/AsmAnalysis.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,21 @@ bool AsmAnalyzer::validateInstructions(evmasm::Instruction _instr, SourceLocatio
772772
"PC instruction is a low-level EVM feature. "
773773
"Because of that PC is disallowed in strict assembly."
774774
);
775+
else if (!m_eofVersion.has_value() && (
776+
_instr == evmasm::Instruction::EXTCALL ||
777+
_instr == evmasm::Instruction::EXTDELEGATECALL ||
778+
_instr == evmasm::Instruction::EXTSTATICCALL
779+
))
780+
{
781+
m_errorReporter.typeError(
782+
4328_error,
783+
_location,
784+
fmt::format(
785+
"The \"{}\" instruction is only available on EOF.",
786+
fmt::arg("instruction", boost::to_lower_copy(instructionInfo(_instr, m_evmVersion).name))
787+
)
788+
);
789+
}
775790
else if (m_eofVersion.has_value() && (
776791
_instr == evmasm::Instruction::CALL ||
777792
_instr == evmasm::Instruction::CALLCODE ||

libyul/backends/evm/EVMDialect.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,18 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
153153
(_instr == evmasm::Instruction::TSTORE || _instr == evmasm::Instruction::TLOAD);
154154
};
155155

156+
auto eofIdentifiersException = [&](evmasm::Instruction _instr) -> bool
157+
{
158+
solAssert(!_eofVersion.has_value() || _evmVersion >= langutil::EVMVersion::prague());
159+
return
160+
!_eofVersion.has_value() &&
161+
(
162+
_instr == evmasm::Instruction::EXTCALL ||
163+
_instr == evmasm::Instruction::EXTSTATICCALL ||
164+
_instr == evmasm::Instruction::EXTDELEGATECALL
165+
);
166+
};
167+
156168
std::set<std::string, std::less<>> reserved;
157169
for (auto const& instr: evmasm::c_instructions)
158170
{
@@ -163,7 +175,8 @@ std::set<std::string, std::less<>> createReservedIdentifiers(langutil::EVMVersio
163175
!blobHashException(instr.second) &&
164176
!blobBaseFeeException(instr.second) &&
165177
!mcopyException(instr.second) &&
166-
!transientStorageException(instr.second)
178+
!transientStorageException(instr.second) &&
179+
!eofIdentifiersException(instr.second)
167180
)
168181
reserved.emplace(name);
169182
}

test/tools/yulInterpreter/EVMInstructionInterpreter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ u256 EVMInstructionInterpreter::eval(
495495
case Instruction::RETURNCONTRACT:
496496
case Instruction::RJUMP:
497497
case Instruction::RJUMPI:
498+
case Instruction::EXTCALL:
499+
case Instruction::EXTSTATICCALL:
500+
case Instruction::EXTDELEGATECALL:
498501
solUnimplemented("EOF not yet supported by Yul interpreter.");
499502
}
500503

0 commit comments

Comments
 (0)