Skip to content

Commit 95c5401

Browse files
committed
Reject DELEGATECALL EOF → legacy
The code targeted by DELEGATECALL from an EOF must also be an EOF. This restriction has been added to EIP-3540 in ethereum/EIPs#7131.
1 parent 1f8823e commit 95c5401

File tree

4 files changed

+67
-3
lines changed

4 files changed

+67
-3
lines changed

circle.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ jobs:
455455
export EVMONE_PRECOMPILES_STUB=~/project/test/state/precompiles_stub.json
456456
bin/evmone-statetest ~/tests/GeneralStateTests ~/tests/LegacyTests/Constantinople/GeneralStateTests
457457
- download_execution_tests:
458-
repo: ipsilon/tests
459-
rev: eof
460-
commit: b25623d4d7df10e38498cace7adc7eb413c4b20d
458+
repo: ethereum/tests
459+
rev: develop
460+
commit: 0ec53d024c2b1f5175e70aba8f750cd4d37d9999
461461
legacy: false
462462
- run:
463463
name: "State tests (EOF)"

lib/evmone/instructions_calls.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright 2019 The evmone Authors.
33
// SPDX-License-Identifier: Apache-2.0
44

5+
#include "eof.hpp"
56
#include "instructions.hpp"
67

78
namespace evmone::instr::core
@@ -95,6 +96,21 @@ Result call_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noexce
9596
if (has_value && intx::be::load<uint256>(state.host.get_balance(state.msg->recipient)) < value)
9697
return {EVMC_SUCCESS, gas_left}; // "Light" failure.
9798

99+
if constexpr (Op == OP_DELEGATECALL)
100+
{
101+
if (state.rev >= EVMC_CANCUN && is_eof_container(state.original_code))
102+
{
103+
// The code targeted by DELEGATECALL must also be an EOF.
104+
// This restriction has been added to EIP-3540 in
105+
// https://github.com/ethereum/EIPs/pull/6359
106+
uint8_t target_code_prefix[2];
107+
const auto s = state.host.copy_code(
108+
msg.code_address, 0, target_code_prefix, std::size(target_code_prefix));
109+
if (!is_eof_container({target_code_prefix, s}))
110+
return {EVMC_SUCCESS, gas_left};
111+
}
112+
}
113+
98114
const auto result = state.host.call(msg);
99115
state.return_data.assign(result.output_data, result.output_size);
100116
stack.top() = result.status_code == EVMC_SUCCESS;

test/unittests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ target_sources(
2121
evm_eip3855_push0_test.cpp
2222
evm_eip3860_initcode_test.cpp
2323
evm_eof_test.cpp
24+
evm_eof_calls_test.cpp
2425
evm_eof_function_test.cpp
2526
evm_eof_rjump_test.cpp
2627
evm_memory_test.cpp

test/unittests/evm_eof_calls_test.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2023 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "evm_fixture.hpp"
6+
#include "evmone/eof.hpp"
7+
8+
using evmone::test::evm;
9+
using namespace evmc::literals;
10+
11+
TEST_P(evm, eof1_delegatecall_eof1)
12+
{
13+
rev = EVMC_CANCUN;
14+
constexpr auto callee = 0xca11ee_address;
15+
host.accounts[callee].code = eof1_bytecode(OP_STOP);
16+
bytes call_output{0x01, 0x02, 0x03};
17+
host.call_result.output_data = std::data(call_output);
18+
host.call_result.output_size = std::size(call_output);
19+
host.call_result.gas_left = 100;
20+
host.call_result.status_code = EVMC_SUCCESS;
21+
22+
const auto code = eof1_bytecode(delegatecall(callee) + OP_RETURNDATASIZE + OP_PUSH0 + OP_PUSH0 +
23+
OP_RETURNDATACOPY + ret(0, evmone::OP_RETURNDATASIZE));
24+
25+
execute(code);
26+
EXPECT_STATUS(EVMC_SUCCESS);
27+
EXPECT_EQ(hex({result.output_data, result.output_size}), "010203");
28+
}
29+
30+
TEST_P(evm, eof1_delegatecall_legacy)
31+
{
32+
rev = EVMC_CANCUN;
33+
constexpr auto callee = 0xca11ee_address;
34+
host.access_account(callee);
35+
36+
for (const auto& target_code : {""_hex, "EF"_hex, "EF01"_hex, "000000"_hex})
37+
{
38+
SCOPED_TRACE("target code: " + hex(target_code));
39+
host.accounts[callee].code = target_code;
40+
41+
const auto code = eof1_bytecode(delegatecall(callee) + ret_top());
42+
43+
execute(code);
44+
EXPECT_GAS_USED(EVMC_SUCCESS, 133); // Low gas usage because DELEGATECALL fails lightly.
45+
EXPECT_OUTPUT_INT(0);
46+
}
47+
}

0 commit comments

Comments
 (0)